{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pinecone-io/examples/blob/master/learn/search/image/image-retrieval-ebook/vision-transformers/vit.ipynb) [![Open nbviewer](https://raw.githubusercontent.com/pinecone-io/examples/master/assets/nbviewer-shield.svg)](https://nbviewer.org/github/pinecone-io/examples/blob/master/learn/search/image/image-retrieval-ebook/vision-transformers/vit.ipynb)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Vision Transformers (ViT) Walkthrough"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install datasets transformers torch"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's start by downloading the CIFAR-10 dataset from HuggingFace. We will first download the training dataset by setting ```split = 'train'```, and the testing dataset after by setting ```split = 'test'```."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Reusing dataset cifar10 (/Users/jamesbriggs/.cache/huggingface/datasets/cifar10/plain_text/1.0.0/447d6ec4733dddd1ce3bb577c7166b986eaa4c538dcd9e805ba61f35674a9de4)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Dataset({\n",
       "    features: ['img', 'label'],\n",
       "    num_rows: 50000\n",
       "})"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# import CIFAR-10 dataset from HuggingFace\n",
    "from datasets import load_dataset\n",
    "\n",
    "dataset_train = load_dataset(\n",
    "    'cifar10',\n",
    "    split='train', # training dataset\n",
    "    ignore_verifications=False  # set to True if seeing splits Error\n",
    ")\n",
    "\n",
    "dataset_train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Reusing dataset cifar10 (/Users/jamesbriggs/.cache/huggingface/datasets/cifar10/plain_text/1.0.0/447d6ec4733dddd1ce3bb577c7166b986eaa4c538dcd9e805ba61f35674a9de4)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Dataset({\n",
       "    features: ['img', 'label'],\n",
       "    num_rows: 10000\n",
       "})"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset_test = load_dataset(\n",
    "    'cifar10',\n",
    "    split='test', # training dataset\n",
    "    ignore_verifications=True  # set to True if seeing splits Error\n",
    ")\n",
    "\n",
    "dataset_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10,\n",
       " ClassLabel(num_classes=10, names=['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck'], id=None))"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# check how many labels/number of classes\n",
    "num_classes = len(set(dataset_train['label']))\n",
    "labels = dataset_train.features['label']\n",
    "num_classes, labels"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Training*: 50,000 images divided into 10 classes\n",
    "\n",
    "*Test*: 10,000 images divided into 10 classes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'img': <PIL.PngImagePlugin.PngImageFile image mode=RGB size=32x32 at 0x1477E4880>,\n",
       " 'label': 0}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset_train[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Those are PIL images with $3$ color channels, and $32x32$ pixels resolution. Let's have a look at the first picture in the dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<PIL.PngImagePlugin.PngImageFile image mode=RGB size=32x32 at 0x16B7658E0>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset_train[0]['img']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0, 'airplane')"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset_train[0]['label'], labels.names[dataset_train[0]['label']]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Loading ViT Feature Extractor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We use `google/vit-base-patch16-224-in21k` model from the Hugging Face Hub."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The model is named as so as it refers to base-sized architecture with patch resolution of 16x16 and fine-tuning resolution of 224x224.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "f8b695d9c8e1490b96429f67b20e5beb",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading:   0%|          | 0.00/160 [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from transformers import ViTFeatureExtractor\n",
    "\n",
    "# import model\n",
    "model_id = 'google/vit-base-patch16-224-in21k'\n",
    "feature_extractor = ViTFeatureExtractor.from_pretrained(\n",
    "    model_id\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can see the feature extractor configuration by printing it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ViTFeatureExtractor {\n",
       "  \"do_normalize\": true,\n",
       "  \"do_resize\": true,\n",
       "  \"feature_extractor_type\": \"ViTFeatureExtractor\",\n",
       "  \"image_mean\": [\n",
       "    0.5,\n",
       "    0.5,\n",
       "    0.5\n",
       "  ],\n",
       "  \"image_std\": [\n",
       "    0.5,\n",
       "    0.5,\n",
       "    0.5\n",
       "  ],\n",
       "  \"resample\": 2,\n",
       "  \"size\": 224\n",
       "}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "feature_extractor"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we consider the first image, i.e., the airplane shown above, we can see the resulting tensor after passing the image through the feature extractor. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'pixel_values': tensor([[[[ 0.3961,  0.3961,  0.3961,  ...,  0.2941,  0.2941,  0.2941],\n",
       "          [ 0.3961,  0.3961,  0.3961,  ...,  0.2941,  0.2941,  0.2941],\n",
       "          [ 0.3961,  0.3961,  0.3961,  ...,  0.2941,  0.2941,  0.2941],\n",
       "          ...,\n",
       "          [-0.1922, -0.1922, -0.1922,  ..., -0.2863, -0.2863, -0.2863],\n",
       "          [-0.1922, -0.1922, -0.1922,  ..., -0.2863, -0.2863, -0.2863],\n",
       "          [-0.1922, -0.1922, -0.1922,  ..., -0.2863, -0.2863, -0.2863]],\n",
       "\n",
       "         [[ 0.3804,  0.3804,  0.3804,  ...,  0.2784,  0.2784,  0.2784],\n",
       "          [ 0.3804,  0.3804,  0.3804,  ...,  0.2784,  0.2784,  0.2784],\n",
       "          [ 0.3804,  0.3804,  0.3804,  ...,  0.2784,  0.2784,  0.2784],\n",
       "          ...,\n",
       "          [-0.2471, -0.2471, -0.2471,  ..., -0.3412, -0.3412, -0.3412],\n",
       "          [-0.2471, -0.2471, -0.2471,  ..., -0.3412, -0.3412, -0.3412],\n",
       "          [-0.2471, -0.2471, -0.2471,  ..., -0.3412, -0.3412, -0.3412]],\n",
       "\n",
       "         [[ 0.4824,  0.4824,  0.4824,  ...,  0.3647,  0.3647,  0.3647],\n",
       "          [ 0.4824,  0.4824,  0.4824,  ...,  0.3647,  0.3647,  0.3647],\n",
       "          [ 0.4824,  0.4824,  0.4824,  ...,  0.3647,  0.3647,  0.3647],\n",
       "          ...,\n",
       "          [-0.2784, -0.2784, -0.2784,  ..., -0.3961, -0.3961, -0.3961],\n",
       "          [-0.2784, -0.2784, -0.2784,  ..., -0.3961, -0.3961, -0.3961],\n",
       "          [-0.2784, -0.2784, -0.2784,  ..., -0.3961, -0.3961, -0.3961]]]])}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "example = feature_extractor(\n",
    "    dataset_train[0]['img'],\n",
    "    return_tensors='pt'\n",
    ")\n",
    "example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 3, 224, 224])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "example['pixel_values'].shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "device(type='cpu')"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# load in relevant libraries, and alias where appropriate\n",
    "import torch\n",
    "\n",
    "# device will determine whether to run the training on GPU or CPU.\n",
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def preprocess(batch):\n",
    "    # take a list of PIL images and turn them to pixel values\n",
    "    inputs = feature_extractor(\n",
    "        batch['img'],\n",
    "        return_tensors='pt'\n",
    "    )\n",
    "    # include the labels\n",
    "    inputs['label'] = batch['label']\n",
    "    return inputs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can apply this to both the training and testing dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "# transform the training dataset\n",
    "prepared_train = dataset_train.with_transform(preprocess)\n",
    "# ... and the testing dataset\n",
    "prepared_test = dataset_test.with_transform(preprocess)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, whenever you get an example from the dataset, the transform will be applied in real time (on both samples and slices)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Model Fine-Tuning"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this section, we are going to build the Trainer, which is a feature-complete training and eval loop for PyTorch, optimized for HuggingFace 🤗 Transformers.\n",
    "\n",
    "We need to define all of the arguments that it will include:\n",
    "* training and testing dataset\n",
    "* feature extractor\n",
    "* model\n",
    "* collate function\n",
    "* evaluation metric\n",
    "* ... other training arguments."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The collate function is useful when dealing with lots of data. Batches are lists of dictionaries, so collate will help us create batch tensors."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def collate_fn(batch):\n",
    "    return {\n",
    "        'pixel_values': torch.stack([x['pixel_values'] for x in batch]),\n",
    "        'labels': torch.tensor([x['label'] for x in batch])\n",
    "    }"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's now define the evaluation metric we are going to use to compare prediction with actual labels. We will use the *accuracy evaluation metric*. \n",
    "\n",
    "Accuracy is defined as the proportion of correct predictions (True Positive ($TP$) and True Negative ($TN$)) among the total number of cases processed ($TP$, $TN$, False Positive ($FP$), and False Negative ($FN$)). \n",
    "\n",
    "$$Accuracy = \\frac{(TP + TN)}{(TP + TN + FP + FN)}$$    \n",
    "\n",
    "Below, we are using accuracy within the ```compute_metrics``` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "e6be2104b3e54c378b6e02220f283ca8",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Downloading builder script:   0%|          | 0.00/1.65k [00:00<?, ?B/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from datasets import load_metric\n",
    "\n",
    "# accuracy metric\n",
    "metric = load_metric(\"accuracy\")\n",
    "def compute_metrics(p):\n",
    "    return metric.compute(\n",
    "        predictions=np.argmax(p.predictions, axis=1),\n",
    "        references=p.label_ids\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The last thing consists of defining ```TrainingArguments```.\n",
    "\n",
    "Most of these are pretty self-explanatory, but one that is quite important here is ```remove_unused_columns=False```. This one will drop any features not used by the model's call function. By default it's True because usually it's ideal to drop unused feature columns, making it easier to unpack inputs into the model's call function. But, in our case, we need the unused features ('image' in particular) in order to create 'pixel_values'.\n",
    "\n",
    "We have chosen a batch size equal to 16, 100 evaluation steps, and a learning rate of $2e^{-4}$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import TrainingArguments\n",
    "\n",
    "training_args = TrainingArguments(\n",
    "  output_dir=\"./cifar\",\n",
    "  per_device_train_batch_size=16,\n",
    "  evaluation_strategy=\"steps\",\n",
    "  num_train_epochs=4,\n",
    "  save_steps=100,\n",
    "  eval_steps=100,\n",
    "  logging_steps=10,\n",
    "  learning_rate=2e-4,\n",
    "  save_total_limit=2,\n",
    "  remove_unused_columns=False,\n",
    "  push_to_hub=False,\n",
    "  load_best_model_at_end=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now load the pre-trained model. We'll add ```num_labels``` on init so the model creates a classification head with the right number of units."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Some weights of the model checkpoint at google/vit-base-patch16-224-in21k were not used when initializing ViTForImageClassification: ['pooler.dense.weight', 'pooler.dense.bias']\n",
      "- This IS expected if you are initializing ViTForImageClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
      "- This IS NOT expected if you are initializing ViTForImageClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n",
      "Some weights of ViTForImageClassification were not initialized from the model checkpoint at google/vit-base-patch16-224-in21k and are newly initialized: ['classifier.weight', 'classifier.bias']\n",
      "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
     ]
    }
   ],
   "source": [
    "from transformers import ViTForImageClassification\n",
    "\n",
    "labels = dataset_train.features['label'].names\n",
    "\n",
    "model = ViTForImageClassification.from_pretrained(\n",
    "    model_id,  # classification head\n",
    "    num_labels=len(labels)\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ViTForImageClassification(\n",
       "  (vit): ViTModel(\n",
       "    (embeddings): ViTEmbeddings(\n",
       "      (patch_embeddings): PatchEmbeddings(\n",
       "        (projection): Conv2d(3, 768, kernel_size=(16, 16), stride=(16, 16))\n",
       "      )\n",
       "      (dropout): Dropout(p=0.0, inplace=False)\n",
       "    )\n",
       "    (encoder): ViTEncoder(\n",
       "      (layer): ModuleList(\n",
       "        (0): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (1): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (2): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (3): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (4): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (5): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (6): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (7): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (8): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (9): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (10): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "        (11): ViTLayer(\n",
       "          (attention): ViTAttention(\n",
       "            (attention): ViTSelfAttention(\n",
       "              (query): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (key): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (value): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "            (output): ViTSelfOutput(\n",
       "              (dense): Linear(in_features=768, out_features=768, bias=True)\n",
       "              (dropout): Dropout(p=0.0, inplace=False)\n",
       "            )\n",
       "          )\n",
       "          (intermediate): ViTIntermediate(\n",
       "            (dense): Linear(in_features=768, out_features=3072, bias=True)\n",
       "            (intermediate_act_fn): GELUActivation()\n",
       "          )\n",
       "          (output): ViTOutput(\n",
       "            (dense): Linear(in_features=3072, out_features=768, bias=True)\n",
       "            (dropout): Dropout(p=0.0, inplace=False)\n",
       "          )\n",
       "          (layernorm_before): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "          (layernorm_after): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "        )\n",
       "      )\n",
       "    )\n",
       "    (layernorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n",
       "  )\n",
       "  (classifier): Linear(in_features=768, out_features=10, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.to(device)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see the characteristics of our model."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, all instances can be passed to ```Trainer```."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import Trainer\n",
    "\n",
    "trainer = Trainer(\n",
    "    model=model,\n",
    "    args=training_args,\n",
    "    data_collator=collate_fn,\n",
    "    compute_metrics=compute_metrics,\n",
    "    train_dataset=prepared_train,\n",
    "    eval_dataset=prepared_test,\n",
    "    tokenizer=feature_extractor,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can save our trained model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_results = trainer.train()\n",
    "# save tokenizer with the model\n",
    "trainer.save_model()\n",
    "trainer.log_metrics(\"train\", train_results.metrics)\n",
    "trainer.save_metrics(\"train\", train_results.metrics)\n",
    "# save the trainer state\n",
    "trainer.save_state()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Model Evaluation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now evaluate our model using the accuracy metric defined above..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "metrics = trainer.evaluate(prepared_test)\n",
    "trainer.log_metrics(\"eval\", metrics)\n",
    "trainer.save_metrics(\"eval\", metrics)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Model accuracy is pretty good. Let's have a look to an example. We can pick the first image in our testing dataset and see if the predicted label is correct."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAIAAAAiOjnJAACYF0lEQVR4nOz9a5bkyK4sjBkAJyOz+tNgNDPNSDOU7tldlZlBOmD6AcDJyKre+9wr3W9pLYkdXRWVGQ+Sbo6H4SX/9//b/xX3g8y/BAJABALpAyL5Y0Dk9U15BF+OIEgCIHB9yvVx+V70i/KrichfRJ4JRAgAQgFQz6EgdJ2FAIJQUklFPupr6xtEAFAkROpPCCU/M6+yPkxfLk7Wp5Co/9bZMn9av+nzB0j0bepzk9vHEYCQyBuTHxIA+4e83Vip/9dtRr+pXyDC2xv4/UAQAgkKoOT9PHKVe3Vuf2KdGkFIIEghEET+GUCQQQQR9S259ugLxMD/5MHG3P++Q17++qfTAPjyEv7TS//nDv6HL/53b/w3nyL/6ye43pefIXegob/nHz+85MD/+pLx9uf/xDH++R3/H1qp/53H/55T5J/+yT89+Xdn8dtP5SYA5dvHMSXW7dP/+IlLyP12/Hvc/O8VBH889P/8r/z/H/+/cAz+WZb+B1nwakPgT88pEKbalt9++R8+/Pvrv5kRf37bv9vv19kKKAJpy+d2an96J/8oqP6ddmCZgfcvl9Zf/ySx0rr6o8S6X/mLxOpLqqWQf6fFJa/7+vX1qfcv/HZp/0Ek/+MhwE0V3uF1nb8QIi3WljEtIPOKvl2ItCWYJjflZghJ3+H1+PM5y/dnJNpCXYbz/Z0vb2jb6+XEROpH0v/3+uaz/Gy54LU+/wYAAUkIiOsc2vVoWNyPuvBlEtX3yvW5/VXMT+8f8nYplz2N25e+3DnJNcIdW7d3Xx8iqAVpo/3+Kf+MnheQ3aC3rpdo9+f+ju8Sa71arm9iQASit5WGQLiu6Hb/r03ZEmudQF2x1Ab68wXkC6U/tH93X8pa3j/dCoJ8ucblNt6Wl+3ecomR8jdrU/Byjm4Si6C0//fbF19XUHdcFj5ERFpIar9qCae6XZfEury8taKy7iiX1PqTxEKfPhEiv9/RdbnrQ+4i8vIQb5d8SckXyfaHG8D7GeF3iVU3p++giAhLYrERSBEhKXK/ovunFy5y5QpgKelaXN0uufYRLxnWaH355IRW+dDX9337pJcrv7x8QcLoLrHqZNbKXZ91u92MF4mFdZPrmtjSJq+dECbbcEmsvG/XjmKDrxCWPrwgXXpe61sr2vtLbmTD7dZI79zejAQE2p9atki/5oJbn/JNPF9i6PVPrl33p121Vm09B/AniXWJ+LqJZSUJqbgtgvAGUvYualG+1rXkGr+rwuuNv5/oq022hOK/3THoNWzA3D/i9pplY8llY93VRl91XVIDi9cVvt6oFjl3qX3dvjoZFqTy+fXifiLBpMTkEiXrjFuOLjlCyrpOROlweb2XAqRAuCTZt1/2h92F1ndIff/zjzc99dL3n3+nG264vK7vBt38LN4kzH84rgv7b7389paXU/o/4fgNFS8agP/xFveb5f7AesL+Z2q9hSSClCQb859/AlbL/v5+uR6JKrmfwSWD/sOV/m88fuex6spuxkTKdl3m/O/Iy5tUK7HuzavIwX+C1p/21stvbxLybrhdD94F0O2d/wnSv2+u2+Wslfzz+crLE1FQUzgRWvCi3Fn1htTLo4AVxePf1VPbEUt3llGhrQFCIAJdl0lpkfR60nfv4qbd/tcO+b4i34/R34O8j8QS+3HDDVCBlrxlKOPkUoUrtEHed/k3q/HSUtc1fdPNKKvgekUbCpAbni7raUmCZfdcH782Bl42zCUW+HKNS8VecS3g/kk3R1hKAS0TNG+1QpSSRrqSEh0MidJ3hZz4hqooVEWskyrNm7crgZUxqFSC2jdTbsBaJ6dt4fVPUl/d9iOFd6j9EWWvVu/awbf7Udjib58xbn4zrhv9TSLX2QUgoN6WJC4rJW9MW7uXwOvFuBlf34D+ckl/UrDsW8Rcz5uR2Q4eXyUW14XjdjIESLnrG/KOnnpf6p0XfdKbYv2jVxwioshVgwJKKCShpqQEEIQHgvCKniaY5IYqRoDBoDBqYy7PtGArFIjKBSNd5pugDEdAtIKdzBAvl75sgZCrVicsFwHxcqWvR2/99XW4mzaXkf6yjq8SC/htN/cKMeU80lxsAYbi7m9inYwWUetKanPfdGILh9c9sdb3OqmXq7s+YGmG9g7KQE4f7Xor05tLzy2dtv7076bc9bbleLbhfNPBd6FQq68iyzw3QAAjQGijijPgQQ8GS27FXVYRnsAKRpRILUFV8okCaOJJRBSaX58u1MIcoGm1aP5IF/ggfQdyySRqY5R2eJEg1z94I1Vvf+fpvejb3+Td+GafNgHI9U+53haN/9/VF4AAWf55q6CXNIEXVfj69tul/VGwCtr3Kafhbt/c/skbvF6+pGyK/h8i3xyily+8XfI6mz9ZVFjs1JKXSmhDSlNKJaqmI59EW+ulIgNBhCNiKUSQJTWX4kspZQJVKOUuserKBQqoigqEMBVNxLHPT15UBe976/bDl+O+7Yn17hehxfXLF5CN2839XVbx9+8CLqkmi8PhTWjdv+MuM/8oZtevbr/701deguL2L3l9aG1V6uKOgMqNKa3QJNY/hYX+dKbfvzEvjyUdbkY6JKBBCagTTvGAB9wxA2cBCw2stL3kG7BSgOFGhS1+RAUhjdzvwCqrq35FkLfnN26l9ZfwupB/vzLXpcvv9+J1GV5trP8FYN1QdSfoX+3516/8bbl+P/P10f/+AoE7vK6HSGViCS5gsYWuCFvYNenI3z/6d0ncC/EHYFkrBIWU65eazikz6IQHZmA6ZkiiqoGlQaEgmmi4Hu2OlgkGCKKUvYiB/z1gUQOqVIEpVGFrwwluEgbrcv4tsq6b8Sdg8dsq5/0awn8C1n3pFjeydk6GRBawbhICL98mr1wk5D9cQ6qAP/5mmdnX3yWBVCTNDBMYoHJxuQFkCICE3y4zNVehLW2pFPC/7WC539KbD5hGeqpCzbMOygwmmM6gRxtYhIekDIuGYGMxE+gkBCFo2z0tn2gWulxfzzPItL0CU5vtDaxSi0KVApYpzKCECVVxxQLSIrhZ+f9wfDel0pG6h9YXxNfNG1Jm+Dds4XeE9Z+B8vJTy1wgUFleIloLf1ui30VCv/oeFxUBO9Dzsrr9iropBSwREaiIiQwVE5hIZ5AypYACcXkX5CKWliUvNzb7LsCwDInbziSUshzAtrHIIKfH4Tydp7NUYYklcUpQIt9OoQgpAQkIBQEJlaRtggGifEr6ItWURBQyFFBteOUtACSAtTQCBcwwVIbBBoZCTRJztevrGrUN9e9uci0ObyvaPxaIXnY3rqAwElgvtNMdVdfnys1Ny48Q1MmtMCLBYCkk4vq2u8TqTfInyds/YTvAcrMu79sFcvu41BCiIqpiqsN0iAwtWUJGkMFw0lNIRKVPKxkV4CoSo063o16X1stbv56UKqRRFGJlYxEBesR0HpPHycMjQjwFkiipIWlaaVpjaZoHlIL8E1RmSDBIRjBIJyQ1JBkSWOHJhJQJREWlQYbOR0ak6BqKYbINGZQwMdIU+fpC5HVXU3qxBDluK7EQdvMAlphIGHzD4yjigDcpdb+fl6NEWR+4fMYlsQgAKjd4XqtzwbzjSosavp30heS7VH7ZBK8Sqz9IRERV1czMxtBddZhaaTqPoId7xJSQCJAhErjY8DodTT7lzlzcL7rjM2mfMdWOKGgBTfIzUXU6jpPPk8dkkKn4qPkNWijMJ6JIuYX66pWqT0niwQmNkMovT6MrginrSkpDKaqibfFFROIy8TcUY4hTNmpQBmSUzwgTgZYlgQrStRC/o4SXnntViLWmab2ovMikIbz/8zeD9s7n5mIuYYTbrwSvf1+/+12u4ncd+T95vH6LqEoCa4yxjX3YpjZy94a7x/Tp4eIBeGLNKSk2liaXDuzq7crW84zidfYBkQY0qYCGSEBm4HQ5HcfEMUtoBSUgUBGqqFEMiaoFrPUtpVI1Fa2UznRyEhL05ORRMaLavhnPUYiiCAgAEUKvSg8BQ9vWqYhlEXYKUGErSpBpUJfUwPXkt+DPq3lThsm39fynYop/WvYXOP1/yZEiy8y2bdv3xzYeNkYaPT7d5zn1nBOYIBAxoQampVsmRcqsIiDr+QuwLqI8pARHOZd0IsAZOCaPg8fJ4+Q5cToivR2oWlp+Aw2DftLfogmMIl1FAuKNOSlKE0KmnSaoz65USqbrAIARIQxpIx4IIEQijTgwyqW3vnsLankn76v7p2X+DzzNOjqkc+eYW9E0rbCMDgpEKJLbQy4u/Q+nUmqxRevlTvwbUKZW7Te9+Ia/cwNlauSdN7Oxbfvj8fb2vj/et20HNCLmeZ7noc9nRkMojNgkHGFpRjejJdEEZAFLBEmjl+6DZ5GTL2ognEImsDAdh/M4/Xl6SqwZQqioCgYxRDbIEFERo14Sq5SjKqGAlWkZoREQhyjcgEkJiFGdEQxneN7g9ENurDSYxDQFCBGGwMthlBlXxGQFuy3DPVooUG3tdlsorvWsv9v+4bVM3yWW/AGDWpoBQEc90Sq8SgKZjsg3PVmStI0+5qXfwVB7+PU0uM615G8HXm4/rDsuuEC6vlZEVbdt7G9vb3/9eH//P7b9TUTd/Xwez+eXqpbHAXq4xpBwaDCSA0fbvrm0gvUc6bshjX+PcKc7PTiDHojADDo5HWdgzjg8zuB0OAWqSlOYyBDd1IbIgL6owlTKFOOKXhOIkAUsdagxNZw7g6AzvKJnDJDB6MiH9jpFGUwaFATopBCMlWLAFHUhMMCAVNrIdGGhsgLXd7uqMw2wkg4u+Lzi6JsqvFv6KMu4pHMb4vVtkg6zLKa/MdV/VxS3XYsLBH0WNwudfdJ96n+QWOtD6yO4/CMBVHVs2+Pt7f3HXz/++r883t4h6tOP7UvMADiZXpv6FJvwCTGsoBwkJMWVoUUyZWR4O5gwiuk8J+fk9Jgzzoh6XjgTD07CKQFNF1nEIBt0E9vUNtEhhaEy4YF+XrZXXlZEBDRUzcNVB+mMgEWCieGMiAj6jMRZSFIRAoV2soNQMhwAOvKNfeM6JklNlAgVJmDtMImltDrLtv003oF1qaMLQ0DmY70a2drsQKcS96v72Yvp1slnBEG5g3s9Y+M6FSFv4Li/+m4zouXsAhVbYslriLhC0Kpqw7Z9f7y/vf314+39LxE7zylqQbjPc05313mKDaiJDKozKkadhCIk/xShldCikuKkR5zOOXGcPGecM87Tj+nn6af79Ci+KlWbGioGbMSADtWhuqntqgNqSGBBKQJYA0sKWEgKP0SDquJO9aw0BgMRZCA8Ijw8pnJOUCjO3tSq0uQWIQF4JDmcVBuEJBXJXZRmVzDN+SgvIN1jvbRPbfsLVasGPAHym8S6E1tyM1pxkdKvcGQlXlx4XMqNL7DqU7m9v/JqXwRWuTDfJNa39+H34xZFXtga27bt+/Z4iBjUwv04Dh1DzERN1CCGlBnQgEZ9qxRf30SodFA5A3nT5XSc6fGdPM84Tj/OeRx++ExgBQUJKTO1YpcgpQfFNrWhusl/B1hKiZAIiogaIwVuarKEl4c7fIKIxSCt0HvKyirjyN0jSehpPlEEaUQQo5JX+44qAKEiUxZvpvdacL4Y/Lx+8Q1Y959rh+hXnOBSjXeHcHEWv8cH/088FrA6O47rcl9fkcGTf3oElujN97DtUiSb5JwlpeI44zjjPNP7i+P0Y7p7OIVQKFWhmrSOEgYxqEET1kNs6Hdg6e/AAlm4QFIP8g1YyX4pEEEllRHNmWvRL8lME3BEWlaCEM8ACTN8VMZ3PQGgt6VUueyf617en/y7Y0C0tjyAioVpF1EpXoBVhjwBLVcpefTr55fB9PLl/SO59Nvtl2uz3LbAzd241PtvB5ODZES4u895zvM4j6faJmLnnMdxnOc855zTp8cs0xse4iEzJA2jtkOjrA0m8U1WhgJ9xuk+p59nnDPmjGPG6Ty80hYiSlIwDTUxakNKbo+Smk00rD9LvCxglZdEQESpkqeD8FjGkVDUVCOMSiDBB6iIpjIUlAKQiMyQDiGhQgdNaIpQhopl+B4t86RriSqNq1KWOmKnf1rH77JlsNL3MqU9oxNpVAozDXEBq53AuvPI6G50AlRkgkaGnNqpu/DW7O4ynBbolrXev+jE7+8vvU6+3iQCMiLCfc7zOJ5fXx8fqps7ITanP7+eX5+fz+fzOM7jnOecp8d0Vqg4c1ocwQgKo/NYQiLgVGb82OnOGeEe08PTcvf2BClODUBgKgYtSImOfMCGlMRSSS6zgNWxTpVsndOhDEkjqPawkpHMQQQyJnULZ5lZrl9UEqNKcsZ5tyKCwQjMCPEAAxmOU4QpXCWUpqApIWKsIBwEgJrcbdtFFRHsOOGrirwDC2IpsRKjhAY1ir/R5gYSYlwR9cwf0IpYLY4R9546S4DdTIArfesGEr68o5Va79zfvYblaiZwJWJ6wurzQ21nyPN5Cmx6HMf59fX8+vz8ej6fz+M45jn9nHE6T8fpCSx6FIngkTCqJKrwJBoQ6VMFIxNBKykUk+LQSOqoRNRIldePllJajKi0fIJo3l2WuCoJASAquCIUjQgWD8BbHhXQwSzBEKnivNKh6DhL5vq6BGVmhrSnHx0KmiKEoRgmZJAqKxArEEpQmtWSK1AHqFYcICWFtOp6ARbFWlaRUK/IV4qujshmCjUqZm4iKqGVobLIY2l43TXjJWm+GfcvCHy1+X97cj1f+v7iuUoPnufxfOoHYH6GbU9APXCc8zjOFFjHOc9zHqeX0PIUWqznk9PDnedMxcfT4ZMJLDZNmnsnPamkFRxCJaBiAwtPY4iZmqkOUYWW5SMqoi2rev07aV4I6i2DJcNvCo3WDen4LD9HIFBVySTky5aozFFGBCKUkmtaiYeIMmxU4QJXeHqJmViQiRIhIqLF3+YqV1QTwWT3MizUj1dqARjscH0ArDulkZlokOh7yVvej2X6mGSWj5hCQLt0pWQy1EpiuAJyF6DkdwC9WM+vLsfle343ttKBDvd5Hk+BReh5uNoToh6YM87px+lzzmP66XNOP+elCmfIdJwzCao4Pc6T5/Tz5DlLaUagCP60XipZVEiJFOMkRNHmeSs+EzWxhlQdrQdFZblGslgbAFy1zbUR826GxE3rLF84SVgseb4oAEYkJ1+1aJkNJjOEUYrFgiEMleK1UhEpzDEz7S6EusytFkqSYOBi8XtFX8ysEZ3MkHlCAQ2qU4MSFO/8oN4iFKEpLBll0pQGZiZWkz9/trRfrbv/7Fb8p+Mm4kpozeN4RuicITozH246p8c5Y7qfzhnuHqny8gIzTcopvhL0Mu9lxjFjzpjBSH9JVTT3j9RqLVtbIKJIffftIUtWXRKrU4luwLp5KHdjMx/y+lgqCQ1VEbkDK31HiVUfsDKnK8Ew+YI0kJvXyZWlKlWoQQ+xLqO9rZ7kt+Llh39Y0+H9zpRYDnXqpAXLY4qIcHo4wzP8ZIphHCZjcCiG0hRDSKUtk/SVqrjuxX866j2vP7rF16/NXNYfkI0Lwydg4OEBSGT67wykpvOIM2MyER50IpPTAxkNqVwCJzwDOGTu7xnpC0nm1YmkDZ5ZBjcHWC9gNXdQ6MlsMTXV1I2XCV9XS0lVW4xjNN3RFANRoZtMMs1kOLCkXsJVKxzBzJiJtIEam70NxDLbnpW1FVbCkUoKOIQmYRWQF1O6whTVUaLXs724+zp99xLHjKKyU7Y7shZAPdRDpvs5Oc+Yc7qfpAMxDGNgG7Jtshm2gc2wKwiBsRzowtaCVNkO7Sje4umvgCIqlewyNfLmZxjpFgrgbV0y0zJ8dppIBLWEv6ehHTOyso8eiSRF36gbDjLVRShCdXZKJ8REFWawtpmQPsZ1IY2qK184adcmANTMdJipaavCzlRBkQlpctSyV3Jf0ilMopYhaN3VCtas5BYBBjxinVtbY4DklgjRjueIFy+WvhQpwkOjsiwEJmImIxghWZ7CSrTtfLV7fQ5uTxtYVWtUBL+IUx3m1Bk4nM8Tx9Ofx3mez/AJiWHYBvZd910fQ/ZN9k04ys3V5SXKijEuO3Xh5JtM+pZ0/V3GLv3djW7ThLvemudOOmJm5Wxq8y66ggdnks6l9JHMZAJCJEQDqqIhFgiVSN83usjHxPTG4Je5WC1d85aX65eW7cXLiSSBpWo6zMyaaeqtxIC3TeR0YdWwRiRFdz1FhJDa2kklvYKUWSB7EcGrTDETIERETS0jYCKZZFodaT03s0hU5mADa6i4aigZrHvFtY2WmJC26l6E13eJFVL2+6SdxOHxPPnx9K+v4/l8znmK+DDsmzymPVznrjM0qBlTsYBlCZbkbmV7i4vckqVDfgORLNP1N2VYDMW1KeSShxlfSFaT9Kgmvlq6zDPxPJ24NDs1VKsNk6goxUKCYhS6MpSpBFwQGgSQAkfHsGEqJinJKrGAuTVFFUlmpghFZwemPlQxExtqaomEjtdn9pSk4EoBhcyN8QwIJrrIiBQtWE5SuZtQgahkrnWUHm08VoKgikAsPTUJJUhWsqkkky8OE54CI1VogmEyPTaTiMqGFqAFVZk6XOUzBakSGmNmGUumU1aUIyWWeXCGPCc/j/j4ml+fxzkPwMfAY9cjbMKCFlSIWeZWm6XJYpfKks7qfXELvx1ye8Xlvl4yC/Jdyq2N07Zu3UuPqoqJpNdPz7xh+CWial1Eum5LqZaxkaaj6QYPyRAgEhc2hg6rcEnT/rV4DdNikHDTQ1IpnokoS+lV9jYBhocA8yIVApzwYMzwAsdSWahonmbqknbau1Q2aW7g3FstsZLNUFVADZmgigiKB1UYrHoyngJFGEQVU2XOcCveLlQqxfDmAIqgC4hujmxKrEiSPbP6oYQFLIE1yTP0dDlOfh3xefhxTsCHw6khzOQlEZjJPjTrnCrL+/btC9D/TV/wlvpwh9YfjmWZppTyYGSiQTBtxBRaVSGDoqUzm1fEUN1hUB3iSWUUsAoMwdrwlfu8gFXOVwSWVMg73oUAHYhrx7G1rmpSEKoLWAAYacekQhNGJl0xnImtwuhiVzu5J5mnctLW10YHuxpXF8DzhilWAj5FIE4KoE4DJ8QEU2RaRhrUlVZs6drx8rKyvx2jErGLCjPCinSABujUSTlDzsDhOCaQzRuUMmknh9GMm+OsasyrYu6/h6L1qu9gugUQfnvD7UdRwBKvLgn0wtYq5dNEXma1S0sPVCECLmAFVUMZapF+t+Y2SYWZhKfdgFWLssiCZCYb8bdjsZdpa1ZRUUlpCkmVKKBkb4xMhQ60VLwlHhVL+IKkUkRt8P3h8QLzy1Vs/652Zt5DgQZHhSKuR8WPl4O41u1PKz0gW39NiauAkRZQJwMZCCvW1KlAIERdzOVwjIlhOGfV+96wdV3AjWsoj+RCU8UXU1i/QOriahax8505Le4ukJxykQvumBEV7EsqroMGogq1irTIgCgDVnMWQklFqIQhLF3zrssSzUKgoWbNkVZmQDb+QHOTLZs7Y+k3eCW2TMSsypoCYEQWmLqILnCyqAPS05uGfquzqtdkTDqp4rTzeZ0N20xHxdaDvQZlElQEkRJBB6bQnFN5Orcka4yeBrgSha2mznovNcDq9AZ0q0ZJzGTcwSppMsIDSX4YZFAH1ZNoCcgMnS7TJatTpot7Zg1kxOPyjNZXXrJmxZelsdU/e+EfShKkRSPXnpS15xCXuMLpja3oIRwL3DdmXG2oDeiAqIRAkyYKY5AxEMEwyIBQQoKR/q6p2tCm0ZfEyqQnLueBUakSvCyw/JPdmCG9OSs7K4GldPUVpi6ZtHCT3JaA2bXWyhUrRSrFtTsjtWfEHeV1Wil40h9o3VpULarKkpDsYmIr0pUBe6feQ8qvcqtWr4PCZbyL7kXQptEEYwzCKJpJFlmWCR3QIepszyRDih79cMknQY2QEISJtoy51Zy9qv27xLpL16tA9JK1XBQPQc0yYQlUUWjlGhRrVcIEC1KZspKoGpuOTRJYBD2Xzkc6laKjQ2oFrHSqmt8Uq+bHRTNACSeRfH4ZSCUd0qNrz78bYSELx0RUS5WGaqiaiiXU2+ddIp5MAwy1W5kwS9ko5QcGM6s0cqeA19sryaHSTruNWcepGoNJx1RvHOV0nhGncxjVKUKJpCrTj3ht3VYsZDGMQ8eDGVhMqzazcsOKjClUGXSIbWIBimRJS/rtENLIcg+DWk42m03OSysjZDEeLbG+21Z1pnL9Ly3hZMk8AhFwEQcSWNV+I3iW5Q521oCoiphYlTMkquwClmQmSlAiIijhEYRRRldOVZaTWIsrFUggK94XJVRXFgDgy+TptXR3D/dwZygYyZ5bMx6hEtqk/hVQvNvjrBZ8BbKip/KvEpcNniWxWuwltDzjCdHaEICWQZ59lSSR4ITLJaumx+miBnERoTJbd6SeEUg1aShqqyhwDBsPtlsIJiMloFY6a5aOdAKkapAiEhXzKhZFM98XKfCgdTO4LMRL9b3A6k+WX4vY10efdEm/7rzoQAVhGlWVHMK8W2kij2aQRkLK7sBKMjHCAxqukYXF2YZq9V0FRDrOlz3PoGhtWHKECFI0wwPJDZblXbjy6XO4umt4a6veVxVCXGxnftstBpg3rxHceq6EWY7gYpFdxazdb3NDs7RqoKtMAcmE1wZnFi0tbZi13RxOc+Z+qtrLPrPCVv15XdEY+1viNBwg6OotFjum3NWVmb9GZnDChtiwMXQMtWGWclyshXgK29X477953PFUPEhjK+/CZRyvtmYJptxhXgyjACZiSFllm9mmttntITooCqEi1EUrq5hKaPqErFyitQv/4VhuGjvOdL04KrnV53lO0wmYylR1M7O0hHVtu6Ufb9Hqi+9qhBARkTwa8A1Y6QakTfZPt/U6v9yuKdrybFs+KugFqRgew0W9aF5XMXQ4LD9hJUzdjrG//ahFSqpnQoVKwtO9y/ilJLZEDYCpjM22fTx2ezxs33TfddtlZMJIUiQilwS/35crh+ZGiCSMJMWMFJ54g5dkmCFNZdBJckacHmdwNQyKQFADALREbOJp7DZ2s83GZtuuttkYEEvzIhiqrhqSXRACInHRBn3maQQvgbuuqGyhJpjSaooulmcwUXUCCkqEgAqMVNFkplJVU9tS3bdjJdtguXUEM183LXZi9Qy5dPItoJT+WxsF2jQF20wpzymzYZjdJkIIE5rH6TGmDxU1qIiZDiKozMrDXMjulCk3jmm8vf9IFLlTPah0+OmepM9a6bQycheNYdu+PR7b29v+/jbeNnnf5LFj2zAGNbsZYALa9sf6vhbi0qcEXIK0eb6UUqtfbda6NA7S6mCEz8A5+ZyZtlBdptJaF0kHcNPxGNtu22OkBrTNtk11U8tkfwGpdFWIenNJbfgtQ6m0ulaXoLJc83oul7fS1URFKwcXAIM+/cQJrygNGClORYAIM5OiCrJAUrrBiVm6Cx6qSTisU8lyexaQynJFtHS9TNFe93RCg2LlLkgkDGWV06XQq7x/IU4JVdh0MzF3nVQxc/qQ9ooEVeNPCUKUN15pvP/4Kx3R6SFnhPjJqX7KyZfU7NpLpoqxbfv+eH9/+/H++PG2ve/6NvAYsY8Y5qpTxCtclhABgrhl6y9XtWjjVVDQkFodp9LgSaU2RAdSmjCIMwKnx3HidHqiKkOtoqqb6jDbx9jH9hj7Y7TEUhuqQ9QyWYKZXiPsVJa4RPoKjKSBDIfo1QRV7r72kl51o9A7ICI8jTiV8ME52ZZ7kihjDFVtvDavwcaWF7Kikh3KbEt2PZY31KanLIRzaallDKuhVkBIgTKiBs5eLZwrA2sKxGmCU8XMh4oqTKWoys42KVG1GNibOhyP9x+MVKgOdZdzhOhJaVZluSmipgYzqSYJbz9+/Hj/631/2/Qx+NC56xwyTVTlFHZcopTaogxQUjNlVeEpc0iSrBOi/xRJ/0w0K/K2bP2jcGhWbsX0OGeaoymqVz17asDHGG/b9hjbbraZDbUhFdCQIDRcKiFjdUpvcXWnplLoanLrlYndW+IyLKT1GUSk5AfdI8AQ+pycg6QClmY6QDKFVkbfL2RpXFx/ULWs/YgV40l8tWwVAVm3kbIyS1qVqhlb8+Qo38jKhliuEVo/BgE4cCrN45wy1FU5TIbLDM229Z1rBJEqywd0WdXj8XiPoHuIe8ic1HGKjVBzUV8ptmpmYQqxodv+2B9vb+8/3t5/vP94vG3y0Nh0bnJufFqWjzEQnsUWKak6zeVmY4k0QVdbqwsbDSIZDBVYokTHrrYBJhQXN1c17QazuYirOrTKjlti7Q2sRKdK9TCCBkMooiKxDJHLEL1IIBZxlE2sJWRxGQmGXpZvFjNZlRgMV9B1wl0Ew3QbY4zkWwWkWrasanvopg5VTTVUVaKcoYshewliLHg0yKWsDRFRRWY22NrLeYUZPRK5B9BSvzupHqdCJ0xEFGYxTGZ3KgxKp/4oEG0y1eeMse8V554+qOawjTbcLB/DbNgYNrbBoMYYtm37vr/t+9vj7f3x9nhssktscg5IMlpKarjAeu73JbFue/tmTnWItpv7jOzGADHIGLrbttvY1XbIMApPn7Ht8dxdzzDKlMzyVBtj1DnbZra/PlIJClA1oLw1OvzdZ3o5+HIFdz/+ctmustlu1ZFhPneGB0NVFJjT5pw+p/eRSFpJfxe2qp9c5KFKTZ2IJV2+Y7kgJt//ndablQO7XEFegllVVb3adAXBSgnxOBUmrsqhcpqcadGHjUgB2Pq3EFarPcxG8u4BHSFjcAxuw7c9NufmsZ1zm9NnpM08xtj2x74/9sfjsb899se+ya6edWQjqBHKEN8EDk5QIfqaNw3c8cSOKkC6sHNTHSKb6ia6j7GP8RjbQ8dDdATFTocdYV/UB8bXdsxZWuHq7WdjDNtvj2z2kqbVslaTyy2uYPXHuj1egHaxtA21Ih+XxIrK+KxRE8w86GC4MEhxkQRT9NHxlkq86drQG7oWtEj3UFVTqyuI5Ux8pwPRp53KSgUMVc3umHoBq11EthsK1ajq1QhyBmTGCYiEKYZhO3UbNsxNARNTdL9cvVeBDFFTASFZFWeD24Zt5z6r4f058z6kCxVjjH1/bI993x/bvm/7vm+yiQ8RC1iERkhQxIFBGKgsbHWUpcR0GZGSNgEkk57ENtWHjd30YdvD7DHGY9vftu3NEljQfcZ4HPb4Go+v/fN5HOfpnsnshdmMGI992JYPs03V0ORtmb6Z3F4xRWn1vLCFb9JLyjoUoHmTi69sMz8ZSu/ElXCEMyILNdvJrNS9RZcLNdP0WkUB6Mi3KhNa5BiJIbKVXH8M8V3Q8oKWgBW/LsothICIAl5KcEWoU962fUj3ShEjJXswj6Gb6chUYcowWHdL6x1RwFIGJIlmwzCOBJZXC/zHZBLF6RUPsz0l1v7Y933b9rHJpj6QqHINFw+RSc6gdeenxSDkVbcelCqlFmQhlaluOh5jf9+2921/H9vbtr1tez1XHYTOycf7sb0/H59f71/PRNY5z3OWMCAhqtaQMht5KwhdDlXGaiMYXoG11Q/0Yn9utyrFidzYmuXsMxZYOuPTPRs2s+cCaPlONzXa3MtFJNzFYUksM1uUx4IdAYkI8XApSz7QivlCVtnwacQjFVU2ViMFoRRBhLgscTuqzxY5Wf5BzBkZHdSqo9FhlapYRRhKqhh0OcogBtInUgXRQku2DbtnlQ5mpTFm8msMs8fjse/7tu/bto1tbJsO1QEWsNxFA3IGjTS6IopDXwxvKsEk5VDGhVQdgowE1v74a3/7a99/bI/3ff+xP37YeJhtEHPn4zgfz+P9/evz63kcx/M4jyMr6c/znB4BIC2t3GAmQ1ITpJPe2b/hKyVO2rlqt+J+gMvdWzevtnVEkuF1pJorYBHMzo1s978TChqjdxykUMMKmKoW8dCoukFPIgLw/JzcS03XXqdY2qE2hoRkKBdZpc8WfEtikSNhfqVIV4U+8waZyjAdo4EFkoohY6nvlu0DaVpUhi7UYAYzjoGxcXPuu0+PCIqCEWPY/njs+2Pf9rFtY2w2xFQMYREWruJwJwd8hFqZNRf5yctyT6+1DWim0JIhttn2Nh5/7e//x+Px1/721yOBtb2ZbSIWgf089+N4PJ6Pt+fxfH49j6+vr82+Pp9fKsc5JwFVK1TpsGzFwU7XjJcsul63qhxNJkqabklB1hq7HZFLXlUvkQzeZAAn24BX4jtoYNUurTjNvdiwbblFI6PXSc1sqeELWCTgnpkm9fOqLcbL7rhR0EDGwyidGMFmzlp8soUUAyA14FLyncGgAofqNnwcbupJlyyvXk2E2l8lQ1ZG4nUyLEItWYYxxr7vN1X4eDz2x2Pb923bbWxmDSxxFdPKvTHqLUj/IrHWP9GEXNEQQgkkth62v43Hj/3tr/3tr/3x1/74MRpYDIxtjnEM223s29jNniqWDDBdSA1G1fJVNkrie4Xz2n1boqBX9aKD03YmG0K31b0rnLUsrQ9TYrEbYqusCri7u/f9gFzYyuXpwvn+pubU0kMkqZrlMy1U1819oXKWCHs5dFUL4m67F7tBRq5daZUghNN5ehwzxhnDwjQU65LaMm1zYkim17O93a63jr6X2c+Me0W1htnjbd8fj0LVGDbSfIsMUCqNNNxQdV+7tojr55WoThBUJRVbxqnS0trex/5jPH6Mx4+x/xjbm9omogiIZnlqNSiJEJ9xjjlsmrl5ZAdsvT0St+2FlpD8wyMlVlk3wdQ0Eb2Rl5y6DKOXtS9cFbCqfuYKXaTTOsYYY2x5qFrWybNUYZPpoCoikmNT1FwBunvyDrLQswRFYkurkhVtY7XLcjvXO9Zf0G6qEQzRWKnx6X/WwKnJc8Yx3VSr/uwaRED2HJiR1pVESZCar+c+p0/3dINtGCBjDFUZZvtjfzz2bd/H2MysizS1Gi6qSshtOFa7MYWs5WwJSGZ3l2AQIkaN08Vp1E3Hw/b38Xjf9h9j/2H7u46H6hAYhISNkHAMZzg388NK66V8IkPRhQuiKgqRIBTRVe59d3HBBO03myqzZXW4Rnj4fKnDanDdmKclwZpIiGS/tecSNHkwxjaq8+C+b/tuHV8qkh+8GaNQpgJxkhYMjxWbbm3QkpblXmgpnAJWZwOgQ0B1mWg/93Z027bQEJVq7uUhhirrQTZitSNUvAJGgKqUpgVz4YeqRaCaXKDIknN69StzJ6Fqto/MFtqG7fv2eOzbvtkYalrt6dhZtXJ16iYXqq7NnSYFBaAEu8FLQNRpsU8GBTDV3baHbW+2vdv2puMhtosMyWBniChVXXSoTm08Vd1xVniVeK59xfp3907ov66oSJ9jrs3IUlaqeogL4eE32CRDXbi6YauKdwpYGV1Eo0rHGDYKVvv+eLzt26amgGT8I2qgfZlGFSbPsulssJuq4DuRK1IKIQO6Jveijy4yFEoyPiuxGS8f0diqmulQsch87oZiULOHimk2j6+RnNqRrRRZkusk1WsyCERwup/neZzncc6INIJ1lPS2MWzbtn0b2zYsbWKJrCRPaf+NVmxcvSjCjiGUxMo+ZiJKjXNyhgSMOkR3sXxs0A26sVpkZ0aaArb67je92f2CFym1DlTgRuVKBL38vMUGZDcqVRWNdMvVIfAg/FJ2BDrjI5VPfVGK/QYWKidwKdfsR7/v++OxP97Sv1bRNMaTPY2Fqzw5ZphYkh0V1e+gatmG2jZlHKupiBT7mglMlxy882XLeszbxSzhVY1K7VQq0+3JxGWZjuMkxFVYqrCyNXgDllquUUbQnHT3OT27SZEwExG1MfZ937Zt23KyyBhDzaQ7c0VHY65Y1JUc92Ia12P5MOmhzylAyPDzDJ/dDSZLOaABU2ikUKy83CzZat4csqT7i1N0e6D3Y/dSEFWRuLyygn9R1dnWWhQhIkGaeTE+5QgKquS7G2r2uqWjGRGaVlIBL22rbVvIejwej7d93yQRPGd9DjtSv1LfJQIwM7mfbD1uBNeSnQktvcIMDHT2b25oXEvyTWDlrqOJUjWoo7jb9CPTWHJMocwwwCyGip2uguwFrBewikrK9pDLxppzTkBETURyq237vm2akisvU7XbCESn7XY3RHkVXY2qyzi4ZFrO50LM7ByUFt6MbClrg+KBTD9M5ZNVNasr6/3O/pGFarWnbaWaqUXR2eHarWDrJIv7aYlGwMI77e66HrmsqwtYd98wLSe0tLrU4Lbv+76XrbqJiEdIp/EgS+lvwCKrv9rC7nIdvpGu3/FRwGIJrKWw60p5f4MUJEE1ZhqtjYu5jdVZi2lsieMU2oyhMiwzvQhSL1UoKyGp6aUq+QhA29FensPQ1X0gs13AsmxERbOL80oPv60r5b7mgaa27iZ0Nuc75vN5fn1+7R9f0Edw28MqOyFb9twoqFtMAw2J3xB1g0tn0t2AZV141e7iXbS2AGxpp5WHWQ1ae6UqeNfLnefVBvICViMqI62Px+Px2LZNgLZlQ9WT67ztwEsWYtFnL8d34fPtuKGmWookeKWLIO7AEkVSLFoSK1g9y5PkS2xJwqsC1Vkf5rmRquHkXWJV7f+iG6KrQRq0uN3pBRp2MpPmLE/QYFrESDOAffqV2gKRdGFMxBKiGVYhfc7n8/n58TEeP2lvh+M4+Hjn48HtwTFoaUt6tXb0FcUpw7sWEpmNmbhq8GbDg2E5ZzAVHxk23dxn5vndfLK1lBCptidNQ6DzCkVWC5abmZwGPFWJqqK25Qg+1vH2eDy2sQGQOSM453RX6ToL3s/g4rEqY6ZaKtzg1ZIMtx/1Nul7AkDIlqURRYyLQDPZnxAYSFGl2vp4EF5xeqn5uinxmkYInQSFViKkgRW8fLriD/Pjug1AR44Y1sK1drRkVYvWiHVQoUZTU/WGV9rWIrDqsyJcTZhETGUoZlAYMc/j6+vXz78p2zn183O+/5jvf/n7X/F2cn9wG5tCJLJt1+lzus9sqJZVFFo9gr4JoYqpVMFTjCXNImL4dJdqP1tGC69QASN3drItuWDlkai2xdhLEM2RZrtZqYDftt1Nq8fb21v+vY2RhczTPTP+lvorzdqQSrvNu33clR5xk9h9Crmg0VgqYNXdIEVY/kcwbXMIqaLKiiyZWy56zpc2hIgwgNBMFdRKu2EJrZgzLWbJ7mANLKVoSOdGNi2+kBURNWQjLKlfqxTdJUIzoQMGmqhRjWamFlo8GqqIvObMEkLp2JOFJ2eEiHk+vz5Dxuny+YzHx/Hjr/PHEcfEnHhzPPYwEaHDT55nzMPnOefMHGAUdSQ9JxrNplWszyAKzfxFMYEwYrrbdNWp6tk9sZLK1w1AtkVWtWEERDMPIJUCfKVIVd7wJUpyRcdYzmBC6y0f++Ox2chmlOOc5fRhfVoB9haIzP99tSZssVWuUkmriIhYpGk5WKLFcpFeY5BAUBkZiVEKbRHlIGGXDZtrlsBKZcdsXZgd4twpIINtc2OImGQRwWpBfnlIfA2vxoJWC9q0ALRdiYsjVdUrTJCCUEOr43Jh13qM82bqljZJhE9/fp0uXwfH59zejq8vP6dEGGmEMTjUFA4/cR5xnj7P6acvoQVeGhuLX4/y9lSQbg9VXQF6+JynmZqJ2+raGqVZit2iCEy1lqozCgKMAMVX59lXTZSWu9kY277tj84JeTzS1Nq2fRuW7eNXuxGIoKPKIINXDZkvWFWd/GrE0MpYGEFRIoFFiKqybUTN/LMyrzQFUhaCCnPMySL1LECrfKCisaraI8u4swNrNn1wZ5Z5UZ3pLI+72ljM24vT0Yb8/egrKUO87Uy9A3TZ71pdVPSKbUhRbqYyVIbKppJmZfic/vSTfIaOOb5iTkA2sYeNh41dIGGmCIkT84h5xHmNnoiaH9jDkxc7BUIqwKKWUTCIORHTx7mNcZoNVReNLq+7xZmR/K+ijMvQMnRIqS7CIbXNvpvNSYsudzCzQio3ZAwzI9zaIi09uIIBqOZ+d923zLhLMN4MwhRYohIhUGomPC0/poqn09NkMMoryRA9U2ISBA1KkjQOZPVEBakyOEGVUCCDNhFM+zTQI4NRRdY93vO27Vbi2guk4n4daWatulb502PNYijC8LJK0szS6xEBR4Sfk5wklMNVdNv2j/398+35tT+fwwwxGlhnnGf46X5OP6dPr4dTkP1cmR1yip5CcoewzFBWknOeW9aGTbOpEZqzAm71kGgbS7NzUXG0WQvdZnBmqK8FROvBTGjdbkfi6XJvIl7xuExckHRnVee/LMK/KwXO86m6BtV7g4V/PlKkVQjiDqxqEVESK/tzJ7Dy0jVbCvQ3NrBuUJZSG7coAIlofX4DVm2Sftt6c5kzN8yVDE5jJ3WgtPes1TJehkpYtWhSBMiYnEEKHGbb4/n8Op9f53HM8zjPgQhFCFtizTPmeZ7P86zJJu4BUE0BiEkwyy0pGfcp1qXS3qdv2xzjHOM03yzTj5DMjXReKZDCKitxRUoJVpcWVQDubgsxWcvX4cElsca25WvqXtz05p0Obxu82OOVHb96sK2YX9/qGy1Y5fJ3ViIj2Qr+DmD0OoLNB+U8AxKWraDtrgoviZVCTnKKENNDTEUbCayihtMWfzH/PEi41qWtXcM2AG4EYaOKtZnbnBRIDpVMhmJZlLUHElvDJCLnnsmcOZkx6JwUxZjHMc/neR4Jne3cJEIlJE76k/Pwefg8j/NZMyjOMzsH2zAI1MVohN0llg4TTb4mpo9xjm0f2xweo7sNkVkl1TQe0JNnmbwJcuRfJHsJcY9tG8MymUIjmAT4KKphG1v+PqvFhaRHAJeXt5QUrwaFPj28Si8iPJPkL0ig+U7e4EWUcVZTJJJUidCrJq1V6GVT1SdpWgwglSwX2NBOdUIKyPaDqCGPmXfdGyKvYPS51XK3G3L5zOJ6l8K9ZbiiU5fflT/OjNyyTFpudQV9nWFHYSrbVUErts0UmmF4BzlDT5/HTPSc+XwTmqQq9CPOp8/Ta7LJ1/N4HucZHiIyOKBiQ8lRidDavYy2keHhBNZ2bts5tm24jxvnSmV34a9dVClK0n3+8qrdTEQ9YnseYxtj2JwGhFbUrgTWGNsSaexRLaTciitqYS5ywd2nn+6zodW5oqUNFucmvXwFFCFCQikRl/XXLkZ+erv9C6clJJDZWqYgYVrA0nRgsjllx9GCjCnQpMxYvjQAjGSi0HoQi5DpC32FVKXxrl0sFy0sJJyQrlKJ6g4tOZivacqWATeJlTOf3BDBIycjlBUq8Bl+hp8+T/djznPOI4GFBNY8fB7zPFpiPc/z8AgVpYQOSyFUjKZWiaQNU1OSlDF9bPvYzm2b2/RZzcmK38w0ilyqvO+FLUCgluuqQYi6x5YptTmUEFKlgTY6ujrGyHmFGTpzcdXAUnN3h4nB9BYrvJaWY3RaTWNpzVlcKqRUJElQg5Hpa1ehG5Ddmdc3LVDV28tGIAEjYajo7CWxClgEJNLIiSjNnkAAOJbIaZahcZVmFqhkweTmftQbpD28bIkWpEfOdcjxD6ulAm+mfYM7ybq03yUMA3CHKUwgiLSMETN8us/C1jzmHMIhcMTJBNZ5+DzOeZzzmPM45xkRqqou3mMocrulxFraEADBrdTUGNvY5ohIdRjuWcrH6raxYizF9ik0W+tItuyelf9RB4ASWAnkeiSnUNoonYwX86kX/JJYv1lYvFtXv9lMJTYgSKs7VqODSrDuVS4vLB2pQlVbNhWOanwJwLI2F7BCyE4DFGjFuNoo+j5sfJ0dl75conL5dHrPN+y5dRFgRMzg6TxrAHf41VwuteblefYGUwG1uuomqlRYzbwSoeHp99XjPBFxAes8PUVabWmvHHS8ttht/7WTSkzNAATDtmHbZmlZz2kR5m6W5XzUNcphaYpO9W6qXkQYpL0eAOy3Q7MdT+/hhMnVC61NeFa4Ntp4j6sS8drd/3ikNkUXKd4fy3i/f4pqjT3HjW8CAMsPuSTbDVhYwGIBa2k8/AYs3kQWLytJV15AbsDO9l2BwKznmNP9nJ5DbeeJc/KMzK6SqGSorMtk25z935VLlXZt9yvPegRnpnD6TC4UdFwSK4E1PfzSd+gmx91sqlubrWx+szHS4hvuW2cJzznDfW7VUTFDcmX14CLya5F6cxSDp3oTUS/A0rboK7goFdjIfJQlP76pC66cwbtHfhdsDUTgbsbU2rKHMVTmOYWsWS1r+YtlvNk1N2AJmM0Htfz1MoulVWEHaSID17c2QcRY9GFp5hZXN9sbKhl4yWJ7y6SZ7LKT1E6A7nGe83we59czjifngfPEnBKhHkJkDCibQkmav519noq96dOcmcXqGQsWtnKSvJ8+T5iCzjjpZ8wzfHagkKJqA8g8n8xLHF0JI52fUIs/RIQiY/OxzdHAco+t2vAxBgeB6VF5TVd3lSUHcbMKFrLGGCJSJ9CcVbvQBQTeLIilIS4f6HKh+OI7NbbqXZeVtMTCCvMCgqBoIMekkNKJ8pcAqxyVTJaUbnbHha90JTUj1wLJAEvKKIoSNRcmu7ijzofjLhJv+G/rTGsvWhXprSw/WzcM4SCm+3HOr+dxfj7n8eR8qp/iU8OtYgMQFSWFolVKmCZxejhJJ/LG2Wd9CzPIwnBGCq2DVKHHAlbMnFYpUvZyhVH2bexjZduUCXETK6JCgfk2tjnGPsYcm2cPOx/ho6kV1hSlbtmVdklvx7upcGNEE1hjdfCWSx7gAlBt5MtDKz/tLr0Wyd6++ovEyv+kBQOvtn6ViAoKgtAQu8S2rj9wRVX1oo3ShocCEdnNgZkMW50ISmxBSA1LYIlCs4UPyIG7iGqjKj3XlCYmYqrDbEuPuVznMkRNJUJIusdxns/n+fV1zOPJeagfGj4QJhzgkL71SHMeUnZjUVu98EsnimpG+NKWTTbtnG5GRQ6K85M+GTNvq6gOk0onKEpyt22o1biZZZ+KphmfSbi+Gp+YzTF8jJgjxggPWrksEunLsHp/VAgX/dfSLJUjMyLC1u6TyoS+iRYUUoV3D+0ucpaCfEHS3VIptSdN1N/IbfZ55+ZkM15M0k1M+nxFVTsgItISK+t600hhFoElJ5lwS8crb4NmU+NkK0Pz1MZL1OJmWUvHcVVlaBZ9WreGbQ/HNIvmmIpq+vM8v57n+Tw5T41p8A0xtPKHNdlShTXHKF0vUCqiVj0ftTmuOrEcZzmNegPWnIRnZNky/aCcsG2MLWWsvMqMq+FOjQDR3j7lLqq5matNMxvpEUMkpEI9bc00si6zBimVW/GVdWUdBJRaiX7rev9Fir5gq5Vj6877Wr0cy8z6jr3EXZrbKgioIkKLFL9EVycfSCmqbPUnTPc8rbRUOXwFFkChJk6zc3vJpj94hXfrdJntplcbMLO23NtmIJFFJseM5/RzOqdrhCGyoQQF1IoMZtuuWy1mMVwd8MH9cfUwj6oeEjelgBFxwms8JzQn46iZbfs+UvyMoWOYDlW78mOXz0VKLCIFXU97RdDbRYlsdLvWDuSK05X6aRyU5JVi9Rthy7q6HOJlS/0GhruSe10W+X4UbfMfvUTUGuXj7nSIrG3wDVgsJYoCWDbNqqoVrG2CTMArtfgNWHckrceydUwlUVWV6q/AWjZ/hiDcs16WOR3QkKmwZZWY4MyZKiqZq1gVJxewrkcXThehM32ec9p5QkxVhBGciAl3CLOQX81sbF34n9VpZreGu7d0Rw9MEXWP45zn6eeMWe1P0hZY9lJOEJDyyzyCdGaZ/tUQ9mb81KIBuKV4rJK45gtvwOpE8OUA8iIV1sqrqdHaeMpfUS5d2WDJ9VYRyvXD7ry32sVd2f96Rz9EQE0p2nFSFUY0s5UJNmm2CbqVSic0UnMKKUGWZ1TGx7JzLv8p76681BSLrEZSK4hAdu95ygwEU3dUc8tuVwJVDGIwmyqhA1PfoI1m/pIqdI85/TznofOIyoXMoI8LQyvCoappWVXtf1rNlb8qSlaPE9FJUXVC1GeZhs/nfJ7zOONMeBGoNsHEEHEJJSM8O3eSkeOyg21UewrVGzd+uYxN4b22Wl3wipUdegsaluopbmTBaTkgGuEelQqaIRow3SNKWcmtD5hRPVFeHGRX8l5JFm28l7BqwQZTEalxLdm+iZ4BFoFLB3pUMgm1xOhosi9v/gLzeqimxFJJW/02lb1VQ/kywpp1KEGdVMlpTVLAAqABC2yB2YXStbkLW7dug0W7IBjCmOHm85ynnEdkGqEACGEYCBOi8zu3bWz7tu82Nm1mnPXlku2+AnMGElnucRzn8zi+nsfxnMc55/SYjBCm0LKcL55diqnBiJAIR9DDaxx15SB0nL5gsS6x6eHVwKJSWi+vKROOb+kxbHFlGC3PVVRkqqjrdA1XDXd3ieTXgRo7jNqqtTszZ6UIHVVN46+6WrwCS7UHK0U7vFlfL1pEfpGLDBdm/6dskItqF5jkGTFKWbfW1gtY3UzDGlWrXv0K+y3jlXWncoSYWGTTpJwUjwaWYFjOJikvLa/+1pbkmweRWzfp0VPmifMMaOc9sYcvJ0dl2kXG2/4w28QUSd6CzeLgnOExZQZEmSzJMTPQeBznOWd0w3gSIirIedAJgmKV4AF6kOJgBgfuUZcIBnLWQRM45Wdjbcfc+XKnrF60IQmUcd2RlgTWqokMFXGIYE52fFCVKDKn17Ut+zZhy2/tfDBdHyiSs65TVdSZpr0CIgQdYQ7SwWzXGCIhQhPUZOoCFsfFkyWhoXdUXeov5VZSAMtmv1ic9DxFmbNKpcbTgZ5zlPLiTHEGzpCNcMBYscJKTrksrDIWWNhK28bFp/pJsWCeEgCEdsshzdG6KbEeZlvVBpAz2HWIQg84KM5AkOf08/RK4zqnz5npJtLsbaZXFg4gnZFVvTqWZ5EtjCqvhcl9Xqb60ksln5ofxVKn3wL9xRQ0J162f7RuE0DgklZjziSVNu6QbWq6eqL1GdvYEhW5IgFtKycHkamk/XKSYDZVziEHYM1xSllFT0sr66GzAa5iSazLtrmMOrv1sP9mrWu5Iy8039L9OQ8COqgjZBI1til/PXKUEjEplin9KV9RbkfRbKIryRmdRtZxYUdMiBUDthINah9mJHkf22OMAlZUvhxzjle0rskZawmsalQxfU5HltVn9n6zPzdP6nLO2rgsaHVYt8yrm7lYO3DV2qyiTRG81EYu33KJbJH+NBEVpTILZzIzIzNi5AXBd2dvneZ3YN2M9j+4mguMmWclZapLJYh6Pm6oygRg0ep/QtxjhdLn1LbdFRb8s9NcsmpZqgtYJtWh3wIKaA7zlZBBnIT3IN1+IE3CF2CV5IwMHtw8qua7y+Dvb66EmGFVtPDYxi6mpERwRLhXGSI5Z/gMZs+T4/T0C2bbN/eIRrYslTvl9EdiAC940uxApu3ipF3C7iAYno1aM+7GC5ElcfI2r5/8ExvxT6fSindh7CbltIH1Ukv8zXEqtbpcv+xBKlzAqidpiuRY8gZWMREJrHZgpLSh6cUd600dX6hazHEJ8gSOrK4XNjbxCU3BpJlvqCIzxIlJcYgD3kHOPMvKMhfichwyoVGbvCziQzs20T581jWuWuPH4/G+7bvZSAfZI3zG6XGcJ+Q548mYc/pxzGPOeWaCbGUZNLCy3JdtIqYmiOW7dZlsrBu4xltGluTmXPEVOYgZkck/NZRQqMhR31FWaNZ5qyoj+4XnN0Q21Fg5yrMzSrMNgvvMX+XKJIVWBFflA9bcyjJ1RHSB64JUIqlCzdmiQRhCR0xwghMxhVPgIlkHFioc+lK1UOIJFYReu63E1ejuYCqaPWW02PyS/znWACKdKgqpuG8qo818+jzhI2SyKg90IybhUId6xpazxV5ViHj1FlYTCzGKhWYxbEZcKgZ+dfRosz0Dy8PGNvZ9e7w93t73x2OMTdUoEtmv/Jxfzycpx+nEMZ1nNcRNmuAivhWVJpsDPVEWK1OL1TJfjXSXAwc1GaYMDaGoDM3oZ4AefnIePtUVrlBQzFoahnR5mZlGDqTOLLiIqK/ymZPp1nP3c2Ybs+kzsu1qae4ksjqU01K9rP9L+azm41dblSiTHS50SaYwJuJEnMIJTqELXLXE1VCsRyaRJFs67sRtnlBGaLcxSKblUhaWtEuT9WhRJfzNJ5ac27Zt+j6mz3HKPCg1T1oTVRSnOTQAFyjKJMwJHExeTwaUqjRTMkdOLWCpDRO11o3dkCgZXNvG2GtwxuNt7HuZ8EDyVaJ2zrDPA5DwmDOTM6Oc9bJYM/s3hb+3uRrLlgqGB1eqcAqbVN2mGiakhKtUq4w0syfiDD9j5jRzOCgYqFTZAKMEntkq8ALIiMxKni2dPJumuIf76ZXm40VQsDtAJogowTV3oq2rQtXywMptrOgNClivqKKfiBPhiikIuzxBZGb5EKxC+GQ5xrKZyj64LPcxshzAFifatZ/NNwM9LApJTNg2tm3bp/s5p505E7AsLW/rymEBS21ooEsQUcm6qPwLUYpRGcaVTVzUv3bNK7hsGZNckxRa3Spoe7xtYxMbANxpx+HO7etQVRDJus4zc4LbwEGJJcARDjrh2Wkv7t4b6TUjl0yXXJJOFYaCSqFI3nEqAjHpJ/2gS0ymxHJE5aAyeaalSTVCXfPuRtZSzHmeKZ2mu8ddbnl4po4h6T+FSIgEQ6jCZhG/h4Rw88DAuzMIMiElcZasipMxhbOGsQtVOYTawOoMzRp9Ict4Lz2YPEnnBpAQkeyQrndfkKhKEUGF2URSabbE8nGeNoboKBOe4tREVT5CNNJlRrDsQQmRUEJDjTpoCBSwdNW2tDVwqcEWFtY5Cz3/R01t6BgCEQmPq9qYFX2cud3zShewEE56/klWC+SoHNlu4B0r/3/Bovqi5KAzEQylKU1CW2jBlbmZJO2rzKgve7VzOlqutAC9GNg/HLEQjhThkASWRHkCnfrWvsFyI28OaKEvl5XRsmpKwWtKTIGrhAmGhErpvqElt1bPuxdgLS9CK4SQmbmZI5WdYb8lFd/e1Sb/yLJM9+m+bTnUNEf6akADjIt7T6ILnpoVnq3bAkoBlDmH2hggyosFSWfMcFUlxCQrutoVzYyiG9+Y9klQXCC3dbnt8w6iMMOZfwbW6qPWEisr/q4SKixHtdLptKCWqDIJg+dDMIVSlls0sMol/u5d/ofHHxdjIeafCIwblPp/glW+lbxYActPeIorVzrhijAksEpQaUPKbsPT8vy/Me/3kOfQgEBa92S2cIdakmgvNIqJDrMxuIe7bx5+nNsYw3RIsqbIWWQa2EK20C3UXKFCiLOsGQ/MmiJgYkMoLpUTTMb0KSTVXWyYbmr70JEbIU+ShEec5zyOQ1SDGMPFDER4PM/j6+vz+fw6z6f7GZysxFTPe1/0SURlTGTTjRxyz87dbP7yNUWdd/9cmTQPDBjwIb5p1EN8jaFFtX7tCF2BKr2ZJmeLrNYwa9/iQsXVrDbLkJqE7U+6wSsWy9+IErKymbJTBXOyel64cNIn/BQ/JabRyTAJEw6RrYBVSVBrEFfVUeBmYy1+tD37oTq0mmearE4hbWatpmIqoKgZBm0nMvzvjOM4tqqhM6kh5CQsZAvZQ/ZQCxHv3l1CB2eltyrUxCDQiQhmgUScjIl5iGw2No63AYXtqbjVTKBBzOnH81A1jxjHqZkmGojw4zg/Pj4+P34dz685j4hZufOYrB4fjZzI+xuLTylMMYcGL1f4cutZlFwIXTlBF9AQJrrJ2NR3i91iM5qG9ZQRQAkDMwlEmiYoJzEXYwzjKl/rRZLqBgWBY3ISiBx6l7pokUGNq6SEIlvbFvcJCSGLpiqDxFmh/cmYnCf87MtxA4dgE4zuuCFXy9cmrRawVgilfAXVyzoJAKJaY3O7UU6hqlIwABWFYgwLQWBLLXRk9srotmo1ImpQBnWnPkJGVA2RCybggAEzRKHQkfmdCp8+PbydH0Jk2PZgQHVDlVgN1QFIRJzH/NJnBI/noVXJniFeP8/z6+vr8/Pz+fyY88mYi0RuWzwtKBawyDZ+2BArSuIautVSItM7ypmig1NBAwdsE981do3duFmYhoijchqy8YEwaWRKlZEikIPgTEljJgqX7ZVdx2SKLp1GTADJAZWzl6HNLFptXiyFSMgSVLHmlQpC6ILJmH0VZWBpzMxiGCmuuolLUlDZQays7RvDcFeFHY/MYmEd3Zd1Sawu9kC52MWFQCAY6aVl4Dt827Kr8rBKsssmJkZsgRRaIyWW0EUMnFV+lHGuHMHrkk7TdHpNYQrAhofCtv0dzPEXJtmZ1+M4TpLneaqpipb7GpF04nk+n8/j6/k15zPiLGBxklW9WCXsq1lB65bs0lxdT9FxPrTmArMvarYmA1w4U1APaVVo3DWGRs41jhJREtCAEFbNfKMaL6QwGFWIzOQ2p6rCZxn2fonSIkU7n4KkkJFj09OKV6miulyyjAI2quigK6ewvL+mSFwwlaEIVQzBpvmQocVtcmVg3W7XbzZWWVdVaZIpOKKaBvhK+aiUwhJ0KXw1RRgBZ8zI8U3jxoFl/b8RFjICw7EpAFBhwMyu2gXu7MhOoQqF4RMAw7PBGmmAzvEI9xUxRDZQmw4cPmc2KpI1MtA9IrnEc855nuesEowJOjlzArD76e7L3O20k9wt2X9dfJkp5UkV9bZMbwFFQoUmNFUTDokhMRDNjCZMxR1OOJTUDttrZJkeCVBVSDUwZ5OXwqjW2hpBX9Hbjp0siw+RExB7aVGtpupVHaKRRhU4IyEVZwJL4UoXCUUkZZWQ2loPWn5xRedaTF4SSzXbnV6BSb1GEefPMwPzCudcrsUKRIkKTSSAESsjvsLYqibqIDIpKiLnikmN5E6HW7uLyRpFWblc4XZKj+PO9AH1GTUIqSydcgBxRkTSlWnCdt5BJbaET49kRn01mIyo9PkbsGpNsjVgMSJEBO7AQvtBy2HOTmDZ/HwoTaXKOBDl0k5kJOAMnE53uGjOvYYOilFGZyoUCDLyyGu2cMvQu9eXj4g8txIWV+wc3TEDrGoDJrC0Kjfz4euRzHD6uVaEgnxLeKk28pH5Hsv7aWBpNitdNQDFNgwzz6ykcglV0sz67ZGyNf+mAhavtb/V1ifnYSBWk91JWAfYVFRyQokvYCVbpvTs0yw5DOe6QV0r7AUd4FT3eU86QP52Tnd2H7wihrJBQ2RM5Mz230k+5h3qNNU67Vo4JrDIFmWS2UoptPMe2lClQYZw29TMIIigz3kIRGdQpscx45icQYeKDLFdx6a2wyjVEkKTx2H+rxQvKj7DhB0ynHH1FIl0DgWC1ICiURkRIEmtwVmWhVwNnSusn84+a890HgQsN0nOu7AVUUvgp0i/ZA4LWKa5iMqLdK8U9+iu06ppxORop+iH4JKvJX0UbftX+a8VHaDZdirX+TyniAhVLAPNGZOJFLG9oxASGptYzg/PPz37T9wElWc/+vBuX8ZgVdZFZ+DNe2ZLUbwRZMdxC1XT3XPLK1BaKCPSXEKLvXhA5ey3bBBTcCgMMjCGxjBRs+wX8jzP053AdB7nfJ7+PH06Q0xsG9vbtr+NnWODDohYFlMhC4lEUtdEhE8/z/PI2Z+p1M8VoV6pXCu/R0VDI8IYEZEdYRUUsTQ02r+XpX6kyXJJi5dmUjHmJp4rHlRJ5SjKHyC6HWDO0snwexRdYqqlyWIgchl7Qg5R7UoL2bKEVsVDAHRiQoJUV3JE7otc6vM8AcowwRgqImbDhsIs2wBUdh+mi7ralg+zTS0dnwEoA+Exfep5MjjFIemcFT9aEs3dM1mFJKJ7kpTh6+5znrPmBnXUMGO47EBHB9CiakbaDmjPJTJdXMVEhuiQsWkMYepBAjPZccAjjnN+Pc/P43wefnpQzMa+v51v7/EgHtABVWtuAeiymowb+jzP83k8n8+MoNcsLQ9nfKvCgFQsVTUkIswicuxDqeeaJbJemwudeWiZpK5IVWEqZij+zTS5AJZlm9RwVXTwBqxMg9QM+l68u1mnolWgZ2Er4dU5ZiIdYck6jnsSahVQm5mpI0AEY86ZFpMyTCWGJQ1rQ4dRmz2Hk3QNF01g7TrcHBCqjXQzI2LOKXK4exlDkRWInXESedOvyc+5M3mtVeUMxEpyENGsOK8brp0iUKGsuIywWnaBZr6pDjUdm3FXjqTYGaSf7kFP3+HrOD8/nx/P4+uYpwdh2/54m3QqdKhuyMurYUGt1qMTtM/zOApY80xjseJNXae6bJ10yEw1JOPaFqSapukHbcKiFvIWlxLJ5l4wkxRUpjDL7gedDpHxAhXmsLecXbtUoaSsVapG5R93X4uoQVEJ/YWqJtfQ/PCyM5s0RSeiVi+qYWYKaqaTB9LNo4KbGTcie8DYsAFFZowE6aFjocrGaeY2iKDKEDVSPOjTBaeIE1K2/eoTh+75vFC1pH3zLt5jUftVXCG1tUOYjVslJ35VHWKFeylB0fW5pmYYQ7aBIQSdPsPh9POM4ziP8/z8en58fv36Or6e5+kBsW1GYOjYt/0xxkPNpZiX1DFdwFOMyXnkrOLznDO9krTZmYEHFJfawCIZKgxopmkoTBWmZXBLqbw0eapdrJoUkmykaSWWP10FL+hoQ1MEKVZQv8EQWQBZFGmnkEbZrWjHtdy1VWRyOQIdJlr01uVf1sE2TyLCAQFc5ZbQ1KFXABwCFw3R/HNXm2rTtjACM3LqACAMujt4lhlU+Xd+M2SXqZ2mx50jQQdw2u66BSH6NlgiWEAJVOvFlgrLf2GtZVb1ZHNImBD0ACI8KFnPmC14j9OzndfpASH0SozOI4nD0JxuxNKAfczreOlKmg7Nd2ChiKCUBlp1CQGaANmlRat1FLTLmZdRtR4pylb+1uX+rQDh6zGWMV+wae7dzDIRozpe3jI2lwm/DBAprK7gYZfD1VSiMefosEdkzyOHuGY2cKXesNpJAmBDalMLHW7droNESg+VpNo554zME8hxfnN2XDmWIdrnfrsBbCqq94KmHiCluzvaGDq2BFZqVBEAkUIL34C1sFUkoFjmFDDEHVIFb725y18RSkY1cNsYc86kDq5ikHOecx7HsVDVkfQ/AEvSW+12RciZ28zczE77JhWhYGWRK6zaKjIJ2QTWZtgGhmJYKsii76vbeZkWIYvPuzPvd0czkXMZ30W1NQ2JVaUqzTdLIFPDc8DKEgsile+w2m/OzDKZJ2qS6FWfydUuLdMpIAoM6VkuZhxbDOcWAFTUkz6EaARJB6qOJxOW8lMBtr2oCrOrI0AHIEhANPsZZGZwic7q+zC2LYEVFBfXgDhLYBd/RgmqSEXyFkTTI1eCwqCai418qNEGx4adQpkaJHTb9jG2zNlIvy+C03ssevrRc359PRNbPue9OXdSb9GUXuk2SlvlQLFWEKb1qEpT2BCOirHIkJwbQktsNbDMMvm4ZkOU29bxruYnOvO3I6cARqaA9iZmO5liplGpVqzqyUuslR5M8kIlNUR5QOXtth7MLow+t4QSs5VZxyKiCjVXVR2kOEkry89gAyO47SCzId/0yj/IcUaTgcp9O/30mXlvKmJjAEiPZIzRbFpiKrc5yaSLEKq5LKp10rY9bGxQi0CITocqIY5qmwkJUK/Rdr2pVu4hwBz+spm5DTcPo2yUBwy26eYeJHMW5MPGJqIRnD7hQsyuYvWWWCW0Vnig72GsfCymba2XSZJ0qCIEVLgCRjXEQAzhJtxUh8qmUKEprTsOm3AYVDlaAyqi6gAQvGJZLDJs2UVZpVNR+xrywRVXT4ll0JAm0FpzX9gimKiSbDDMm8yC5gyZMbZt81UE4xESq0TN19QhDw9qpCGfrvAolA8YsbGANeUUd5eIM5s6hDsryficWW5D0kw2wIYC3YTNLHPrmfCuuaNZHig1eynd0y1ryHYdO9Q86HAb1LOqGNP0QfadKqdtKfSl6QBCLDLZ0GIbQdb1uO2+OT1ApuOyjVETMTnLq/WWwen9nafPerpywjI0HhH0Jt2R7e1LvYtetTRuqFFHQxJV2BS76lDdLLNAMzMxE61oQlFaxUcKSbfBHyvLhShbCJfEYnhHBXgbc7VC64TU9m4PsT4pfaPsVi0EhHr7XCm3MBu1bb7N8G1OVzPR6D5m3fGjW5Zq6FIoACCW/UvUxDaM7L4shnOCk+7wYgzSXTqPcwFrDFXViA0C66EjGSZzjxzVlxKrlSMaV5Y1ZGPfdewQ86BzjhlmoTpVkkVNyccICc3Ch2IisDSjiEiImtqmFjYANdHQwRHcA05mlZJktbVokIgOBJzzmBXb7Op7D6dHS6xMxY8ci8KSkFi3P4tMwiCqMHAgBmiIAd2uiLJtxs3kqrepoUhQrRJLMCTrG67I0VJ05cfd7HkAGLGAlefYpfia/oNV/W27TVg2+qLCwPsLWhzegbWN6ZtPH2PMc87Fm5NlYEVO9eDU5UmI5IQEIEWAWlRbQFRD1fA0eiqHZVm+0ydJMuPouVVWlz1EVLG8LGp30dRShrtVI+Xdxg6xGZwh43Qbs0stSRb7wCynkSY2usd9EZuiIlY1jwTCREMDRnhmTFSeDEhZQarWfefRjmAb6UlY8dK/ncuaqlB7U0uxiGIqBqQXPYRDY6gMxdAYlX4om2KzjCtf2esitEUulaGduR3dZwbf0PTiHN4kVnnd2bm60ja0S81Lyt2gsw6+fOQC1oWtZEnnrT6xcLluSsNLvUrZcTkgy2EcVSNtYiExJFwiJJwRMItboDoiQgSVR7z4kna+exusX11b3Mx67M2+bbttO8Q06JT99G34sNPMMsm8fPvI6jvcehvfGPC84214qYiIpSC2BlaUBxPwonenx3nO4zyP4wJWnW7mpuMCFttUkReqJO+6mPoATNyoQyLNqU2x3x75k9E5+9Y1EZoL1Xb6iinK+iG/welC2Ijc35CbmRBNqDZLxxKC3xIFC1UrRWkVD/W9zN09sjajS1+LtqjFRdvvMWdAkm5HghtFTSY3o4SJUk2MyrQ1xRSqegISEfOccp53Dds7uck6EGuelgdZ08jMFvmW26CnKW071DToIfvu++Hbtm2zreVgjYUhoGHKOWVOc69a5w6mlTA0QqAZL2FlyMB7gACnV9Qp2HMDyqg6563io93P5e63Q5rfY1LFe5m3JEPNMFsDcigehofpbrqr5GMsYMm3YpvCctpJ0hYTOgmrELCEFy/hcgEruMIemWGYQSOyUo4KDC/yiisAXf9Mpr87BSyJNYbNnNegd6G12rXVrQxCwvpL0zbUxZGgLHpVHbqJmfgYY9g2zkPVyM52l24kwsiiqD7n/nlDOZ3HisvihXzL1iJj30WHBYNyTn/sfrReytAcMjOHQYUJp8l56pzmUz3XJ32CDORX47J02yyghKhTdBIiDsJJ+LLcIydTRJnrXKQcUMOZa8NQVITXvsjT38Y2dGgM6CCMMYCheAw8TAtbprvJUN1qlGSiimtBF11FVDeEXHRNEZQuTP3V6BABMHyeSzGx03HTQJDKkEpsoVOyE0u3AG0RQ4C0N1rKtIWWXQx8SyxdkyajauciB27XOPfuzyR6K4pqsWJiWe/D2LYxt3NTUXd/Hoc9h6hc96Q2W10g2K5otrNiDYkLwnojqF3D5rdtAQvn6Y/dn8e5bx4e7q7uQXgEY9Kh4GkyT5vnOYdOBUw7/by4Z15R16GiQUn/xz2JjFSOd7szpnfuGRY/DXSnclYwOSQzaa16OdUA6iGbxqAM0hgbOFQexn3ow/RhtluGzJBZJZWqBZGWTDc12BYVm3tvDiBH613NdYgLWMgObZl8HN3BB7eG2LU7UsVKsw9Jwl0MRNFbdbndbnHFdTrjSyo0VMvv3WaSDKWsenaA2TXJDEaBZaONJNuoBoHThpmRPM5z23cbQ2u2VlvWL01jGWvBUp1VbVkzb8uRHWVniQ4nnXjsvm/zsW/HOaM6J4hL5rIEwSmpCvWcNk+bki3uFsKXpVexOOZUNhRVnkuQQ+E9Isd6zAZZit6qHLgsiXuQLuPNw2zLdk62bdvQIbFBBjkYA7GJ7MZ9yGa2Fap0aA7nLte+fLMFnfb/qhKjACCX41biaPWmvAGLnYDL7ickeAnhZAy7Uxurc0SnWL8o16VJy2hZFWU3VF39dTLg2Nt0uZ5cHsdNkWdGYsYtu51TZX6MOdd0yaqurSuqogUPSpbZVNoDK/EauUPacbNt2Na07raNIbZpcAa2ce5p0m+nz3GOMczmSmlhhNPdkiaYQ2cGiQQiS2hm4A6LGWwuqvIfc+bl9JhO90RVdFiCpf+kRiugiFrJ8rgMdnSl7lDLh5qEgYNuHAM+BMM4TIatzme6Kk7RllWjK+vSyM6+bm4hbut0cyC4grIY51kSC0CIZDu0bpvdLUhK3bXx1LGyfuD25EKZXCmI349e+2WNrqPwDMnqus4cqGx60BndFSV3GGLVOKxmqlW7kafizJa7nivszoxOthdlqzbfxp686Lbttm1mm9kQMwiHxbbk2LbN6duc58ov8lk3sJXseU6FMDTvY9+U3A0ZcQFFgzIjzjmPevgx/ZyZJV1K0AMe1QqyFmQBKznq5ZpkoFiyk28/Up5J9rHK7imsovFei2uCVinu3vB5Ay8DHZ15oMtk73qmsl1uwDqOvOKO5hBS7SRFoDXAlt2Aa3mFXMuY/1opNAWIJfdXosNLwrJ6Du7WkmmVsqGSudSZQFcKs5nU6XUViiSIRZXCiHleSSQdDE4vNj2sY047ZvJ6SZgFkcnf6UPZ2Mf22PZ6jG3P6XCmBlWSdx25j+FjzDHObZvn6dNpHjHTB4zw85yHEBHuYiIdtGM3t83iFAsRD5ldYfvV0xaPcx5nziGOVoUJrJJaeZelopZleSkKTwFxysXggC60MnsVEuX1mdKUlbTQ3UkAkaLJI106SGQv2WVlSenfAlZSLhdhWn+N43jmqUHS+ish0e0aulo2ZwhKc3np+7bB1qo5wcCOx1arjN8EVhpdAcCWAOtf2ZpR2q0/wn36nPPIvyKmMMtgkMCiz+N4fh3HOd07MpPsh5Pn9Odxiqq5SdUYpsCqJoA29rE/tv1t39/3x2PfH9v2GGOzHjtAufUQGGPfNq+M8xn7HhFg+ESVFHvM83zSY87qRZZ6P9Vgri4kqA7xwAzO6cdxPs/zeB7HmaSonzNO50xxtXLt2w/pJcsumVnbVSIqOZszKNMFhFE0sjthiGTTeqrUyLxss1RV7qkEo7KsRDxbtWDxoSUdKbhM7yztXWfXDS3H8TwAlNljwwgdYlpZF9qqsFG1KAs0vkvlFHfNjOk3tnAJrRv7oGYaOdEvEwsvu9m2JGC2LEgUwOc5eXzNec4Zz+OY54FwIK6s7ZjzPJ9fxzGTslCYCkHV6CE/qFbBK2eyCh8yerPtb/vjfX9LYO3bvo2xqQ3NMt2254bp1qHP6T73PRNXEDEFCFc4g3NOOHz1ydAClnStQJaRTWI6PDhnnO7nmT2b55x+Vlprjn+El7dYM0bL7S6tairI4laIEVlYxiQFK1d/hCpVMCAh6sJQCVXXqn0tV7BkTY2VDYpDAuKQLKus3/bCVsZQdcyLmyokgPF8PlOQiqrmOAFRNetGR9mwqjIXVJaDwzLugBsFoZDosBGxTO0mHzuTWlsVSvU47bqL7Mn3eOzJwqgo4c/nMxjn8wjynH4cJ32SrpUJFAx3P+dR9azZlzv1LEU8cE6nyAiq2coJUhujNODbno/H+7bv277nqKA84bIfFxVhto/h275X6mlEp/vQTwbI6TMIn1nNLFzcU2sWlKDKCrDgdE6PGVVxMzvAFakEmW0vItuJewsHEQrVAJhYtX1SigYxCXh3iwYhYUIjJtQEQzG17PxZ9s7y6iuJNljNRoOac9VyWG5XAdaTegMYVy+LC1hH7V8zywwx7ZgzcAMHdEmspUjbvxQify+/WfX3Q26H6tK3Kt2qaAzbtrHv++PtsW8PMyVdVcP92J6qlTU6PSKmMBvR+uqHXbkRNiCWuq6wlQSRcGQdq672f49tf9v2t+3xvj3et/1te+zbto8edYjyquMiT8cYI7aN3YI7k6Ej6UMHkXx/BMKJSOa1fEeI52iMwPQ4nWfZ5pzpumZMvWqByEDkrEBRVr+O7FKT/mwnUYhldx6R6vsqlBmkUBwiVMUIMdMhMkRmcaG5b5SZjIuUWLqcVFY7T/Oq103UZHJHDXVqqit7UnfOOwlgfB1nrq1ZDKqYa8QKkWORDi8IaXi1QgRXovIfQkf//pAV4Or8rX3f397eHvtjjFHAipizip7Cp2Rv8wDDq+UBhKKiQ0VFR1uZnWHcRXE1Z3yMsW/bvm/72/box/627W9j220bdkmrYIYqK2uQZtw2FtXkPmdkCSzJbJ+QTFlaoR1RIoW5Ak6cmaP8Aiz0mIuMRizHXoHkEls/ZDpocRciOvKRVUwwQ3obooQ6RbPTHbOVgEzwBHtChqZe8xBDu11ssi80Ijw0H52mih4SpivrlUz13BneF7CeZxEggwHTsY2towda87myDvcGKb5KrKpZzu+RCsmts1xt8LoYq1JqPSVWMfXImJ2OkcB6vL+9b9sGxLaNLB4FKSr7ZsfxPI6nn8/pM+bpMhHZ45JWJ3kFlm+2nY2cs7Nt+75v+6NaSr69P97+2t/et8fbtu1jWMYgK/0o+60BZjKGbIQTW5Q6SzogS6BUZK4mw0B4tkdYFUPlpp0Rc/JIYLXH1ylO5VVfDEKHzVXAjDdEaLHwKUI3G5tuu45qp7DmiIpUKy6HTmG2ZKjeaFnjH+qAUaxu2IoG8lqu6P7lRcX3LCdR1AAtNLDwAqzPrzPJDQtQhm4+iuZJCkAEbGZyQatN+FXtSDYpf8HvG6q8W7O2RzVTJ8ao9lSZQbyN8Xhs729vf/143x8PVZznW9rT+zYeb/vnx/vX1+fX1+fz+fl8Ps/jWY0YosWsyAr/FEPb3SjGVlG0bd/3/bHv2a707e3tfX973x77GNsY1sUFmVkckDCX2HRAHbpR07D1DCGnthRxNc1Gj6e6WUwTn+Ez5mTAw6fz9Ghg+emYQe92I5R2tZe7h76K/BUZAW2udOWO2bBhexmFWRi4En01myTCBWfn4pFwyhkyHNXJs+tui0K/Fu7qGMhs81S5opqTmaK5rLicwraxPp+nqppxhEDdZhqMnZMFlWwOdjFofXa8bKyKLyxU4ULVal5dmMpo/XnOOVOcRGzZk1uy7/Jmj31/e3v8+OvH+9vbGOru72+PfPz46/3z4+Pj8/Pj189fH78+Pn59fY3zONwnu2i7uIrr/6IxOiFmbGPf9m3fHzUd5fFolmEfw5KJFmG2+CGDcIMELOCJreSKWotlAoZMVTWNaTSd02KanOecp1MY2SsFqf5O5+mYgTO6iU0GSaQKSau3vVb236KRsxFyBnXKfqkMsuxCcJE+KB5SYBICF5ldaezIqSEwrs5pHZhbVFRF8e+Tpyr3JSN2IV2az/uj8QCMz2Oq6BjcKGIxkpSr/FprO+sqKvyznXQTVAt+V4rB1aRxlS2d7h5UVWVlgMFUhuk+xv7Y3t8ef72//fjrx7YNMn78eMvHX79+fHx+fnz8+vvvt/3vfWzDbHyNL/cZpOJqlnNxZu1vmtkY+16DxffC2JZZDNs2dhuj6seBbvETwkhWUeFK0WoTjlEPjkzgZPmNNA0zncPPATkIlWzlgpiMnCPUD/FGVfFDTfxBFTUQy1RMq7FLT4hNzz29kOKUR1FutRpt6apQNVQ8/S9o0hxKUc80N2THjTan2ZKrbKdMPKzYbWawI90IuVRhGYUvVWHj63AVjoDDdMTunCFRuXWprTM36qIuCkw3C/5uzZc07Khv5ajcrKvVBdSwUiGgKmt012Pf3x77+/vjx4+3x76LYLq/v729v739eH///Pr8+ett24Z2Za6O7ZxnZEp80RdqHQcrA2uMsrG2sbc+HFZlRDaG2IBZXW+J81qeyvkozjcDJBSlWIhtatQR1oqYlWqeecYiQZlBmQF3qjO7R0cSpJEFLpCO+5eFlHkK0CpD1qJqVdVQXnTHKnKgG7TyHFEWby2HSNLrXn6lZgc9RLbIqsQCWS4UMtAFIBM//epWUNhKgqcHBjZZjoosvQArVDGooTTn7jhLvGfpokLY4adFI0j5Jv/24GW+/+FIMCakxtBtG3t2/9+3x2NL7fT22B+Ph6pEREmYbWz7pmYEJzEjPAAd4zyyW0gFVa+oZAOrJNY2tor855hMtZrOkm4UAYkqOloJEs08rT71zXNWMK5QVj/WAQ0wM/m8mxNl+ysPaG73qEqnKv29QpxaabKFKjPRUbPXGmGvwGq8N1e9TJEGukZSEnVCS6yVB/YNWJctXWKBa9ZP3PzWF2Almr8B6zmhBhdgYjjOkEl1asBCTEtiZbdIg/iNpOrmGK+8FXFXvd/A1G+4NdjctrFv2+OxvRWS9se+7Vl/NWwbqoLqKtHlQwTck5gOiti2ZayQXVx7UWZqUMl1agRoSEEg/d0AhBTxHHiMnNBSPRRzdECVe3jEOf3wOGf1IaqH83BGdoYPMCQoTp3U7j0+Qjxy0l5uKuE1A2pRji3q5EJVAUtMO3Ohdk6CqRIbqJciqrvfcb1SOxoVCFCpRIvSMlcIrr3QhBfxD8DCb8CSUmCvwHJRSIhIyBY6Q53qyJEjg2kPikMXtuQGpLKqyuRbJ3lL5iFfJJt0QSyA1H2PIhfe3t/f3n+8vb/tj33btvRyVi4Hhgm2mqMRWZtDUKBj7G/vz+fxPI4sbqm087wFqLIlBgyAZ/vm5JhcDSKZ3pKkX0XUF7Cya3aQ4ZwMT7cuwy/HfJ7n1zG/jnkcfp7uczIz8D0ipxiHnCEOcxnUgAlo2elKOytB6u4lAqQVaQpdE7PMv8j6dGntv7IYOqqW+qT9skZv5gZ4uoqZINclDAuH0v7CXWLlZ4VECKt8s7YMmOMebukPyU2tXJsC1hGiUKqK6xZ6Uk9mj/8RkoN9QR09PNVWwBqLUkvr/pqZWgjjq+F1C+3ktAvZxnjs29vb/v7+9uOv97/+ev/rx9v7++Px2LbNqnfqTSqaKTjYY6JDchjGY39/fn19fX49n1/PrBb2cwadKbWFStHwqTTCiTlkBMyo6qvFFUuJEChRlo06k+h2r2zE4jbnPI7z6zi/juP5PLKONPxkzBRcDA+POZkaIGTQAJoglDTLryzZWcDqcGsTJkvlGeySuys3hld2UGVjoumCMhJT24oAWvwTdaUOlKiUWknKei6aNyN7IUiESFY2BZgjcwOXJ5fWZ7qqt4PjcFMoXYW2U0/apM6eHyEFTGPHDUpCtTYkYv07UyFxEcd/wFV1hTAT6L5vj8f+9vb248fbXz/e//rx468f7+9vj8e+ZR5oT8ezS9qZDNq2bW9kqIkN2x/b13P//NLtQ3Q45PSM16HKOitRMSVBmIXNMAtTE11ufFlTeXVKCEJ7c6TUamBxuh/u5zG/jmMBa87pfiJmz7R11iw7TKjLCFMgqgltEiPU29aXtrYvv68JuXQSs5lHQspKxLbiulrA1GKzWexK1IyOw9SgnZt7mQ5JkV/JAuRdkEgj3SGdccVu2wFAVwFr8Zk3UwfgOEJVNOPdR+gZclDP0DPkTF6U4tSAEkZYRZXyLG5WU/qMuG7TZebLhSobZmNkw3Ds+/Z4PN7fHj/e3//68fbXj/cf74+3t8e+jVH5FWSR/ouAFjMZNGIPNejA2DB26JiUY4Y8T8oxA+d9xAwiOQRVVzUzN3VdiaZlk7KLtti7uxpgEFWMOkl3nOHnjPM8v47zmcA6zzln+Al6Zl5IjbSghwTNE60gLFPcVJJckPvWl/qj/tfmAGrSi6hlzlxkbp7cgFV56mk0delCPdIL7Nzg/EzewFvKrwhZ1DCBzJW6BhZ2Kl97G1nCiBuY75JE5AYslyMfE0/n0zmc5SUFgtLER7net8RkdGBS2t5qSF3ab/VgG2OMVOpJK7y9Pd7fH+/vb+/vj7e31IOjMtdTGcnCaIFUVdVgyLbxGA7bXOyZeSOtsKp3RnlH9XYtbKmnNcMK0rESlv8ALLJziJ30wIw4Pc5zPs+aJH2cM6dy5UxbQZTtS2TfkCgfiL3TUoupvgALuIt4XLc0LzuNsDStWgIVKEpiyTeJlY8csCJc2EpTrt/bXmDrxja/iJ572TmiS2S0eq3vwsvjkliiUnbq5via/Jrxefjb09V8DlEQtf2wHAgthDXtIReYeh1vmLpCdWPfB7i7mQre3h4vj0dlQ21b2mAdGf1+uzM8xYgqkDqnZ1LvcfrznPn4OnIefSnrPsUM8pglXSS5u7kaAF6BywtY5QcR6BgOT485/ZmpnmccZ0QwnH1LMnosrSmyYgKlQSDsMTBLha31QDsQl8hfSS3yklmAqsGQu2nSn9IlzFwyZrEb5WAlwsoabnn5oswo1+Mmi26I//ORryxghQMuX5NfZ3w8/fE1t8dB1cdQE0rOfnMkpCQnRIristpWek3XWQg1rakYY6QeLvtPRcJdFe9v70l73lG1b6MI8Aw81865Wk6k83+e8+ucn1/nz8/nz8/nz18ff//8+PvXx8+Pr1+fX78+n8/nM8fxEnfDMuFumv6UVH7Z7xILoHZ8A1JlJplAUnLLPQE9Z5yeoeqLkiox0KZHLny0wZBpnQtYbPd+iYp2glIa4dXSKPG17Nqb7rhskxK2qxQqgVVhzUJugaBJRRAhtaOAVRl/4bRSE/q77lBqeuP6yThcMrMRkzb5cfj2PLevp21bAMfQzcRAE0oO3yhn90U8AYIue4Ag56ir0chBskzDss2GaUSY4sfb+/uP9/f3t7e3x+Px2B/bvnWOXXbMF5bGz09OksBjnvPrefz6fP7r4/mvX59///r6+fHxr3/9+tfff//r758/f358fn4dz+c5r17wYNE35VyXZ92ECCulimVdEB1uxZUSpCES1EjRdRWU0j2laG6oNlfKPRMIyDR15ZJY7amVM4h2DVMmX+iSgnYF+gVyVVmR68as40Vu4TJc0nm7LJVLBsUqkqnMlLrs7g9xSby8V+VXVjJWQbKdhT4djoOiOV3FoSfH4ePrtO1Q/XLGYxuPoTmSIOeJjXRiqYpVcsHS/SURAFAUSjOrsyyiWGAqcxgjTOX97e3He4qrx+NR0bseznsjktlNxAMePOd8HsfH59ffPz/+x98f/+Pvj//6+fn3r4+/f/76+fevn78+Pj8+P7+e53lkYXrmMC3pQ6CAlfcS7Aon4MLg2qF523LHlpjJdMogquIv+yhTstWWFAmdglb6S7XqtCgUCVZPxqXCFIJy+Rsyy8honVCLW/BC/7yjT9Ioltao0qBcr0i8cunXu/1dDv0FuMw67ox0AbmgKWhJXDvz9qzQNs4QrWHfkBl2uD2njqeoTsbbbuc2dtPHkM00VJjl/dkZLdEkV6OvdmZDaui1ZYKUhnRtCLZhYJhJqsK3t0eZVvsqDdSlS/pUK8PpdD+O8+v5/PXx+a+fv/6f//X3/+O/fv6Pvz/+/vX569fHr18fn59fn19fx7M6aVT14JL8qZv4apGwKulaEkRunbas0HJFQ6u6puqfKriRt7SscuGtIUC9+7JvUmhFN8xZPhrvOggLX/3V1+pXHLAyt/rzGw2Lx0fTnGh34YW/vIysu/q8exG4rmqBTRrwqP33ktew0mbyvWNShBrpOThthj5PMYWIR5znOHd/29Q3ewxz08hRrQQFWVSUd0IXQZo7EGvAQNnwgIGhstFUBGb69ng83h5viaqxbaP6K1f1wT2sSEYwW+9/Hcfn1/PX5+ffP3/96++f/+O/fv6Pf/36++Pj18fX58fX1/N5HMd5zHOe1WTjBVj5qWtVLrF4u+3rbt2AJQIxagDRQZKmoK6dv7z/q7dhb+GFqgth2TK3zL6bWfFqFd94yPwnl9x9sWquM0hU3T51we2CULkXZcn3df/2qZd+xotzhu8v/N2WH75GY2b8bIaeLs8TIk6ePqePOYe7zWH7UDfdFEMkVAZoPSr6dl1cN+IlUEhW2F8lA8+Px/a48leuInxcjVlJZJcfTI/z9K/j/Pw6fn0+f318/fr4+vnx9fPj8+fH58+Pr8/P59dXt6nO/mv/GVh9U/5bwKoJ1J0S0FbzMmdv937tsDssvj3/vsxtFd0O4vYy/sOfaNC8vLnjfnK7sma6XqXZnwB6++B/889/+JUAwIjyZQHKGZQZcs6s05jh57TzHOdm52mPMR6bHqaPobuqm24mGxUmVpuvGLaUmZ2IPOc8u2I2BExU7WPsma0wkt+qLGJou7Jpk0R4YM44zvk85sfX8fPj6+fH19+/vv7+9fXz1/PXx/Pj8/j8Oj+f53HM44w5o1LwqjvKBaMluvECrF4Wthq5NODLUVtlmbL5V3Pmt5e9bLD8CfkCLLwuZwKb31c4VVb9NNVQC9oXPKwPTAF1aYqbxMKywF5P9xvIXn75egOuWhleF8Jlv10anABGdXHKH6VFelZLltPtGHpsdmz2dejbGI/N3oa+beMx7H0bMRQD1ZxH282Wohzd45xzzmOeR/YaVOFQUbGRqTJDt6Ejp5lfDR3kfuMIeuCY8XXMj88jIfVfPz8TVT8bVV/PeRx+zJhOD0lGl4tsw2skq3HbcJICyGXMCIRSw9LYEiuLV2u9rqTs9XEoJdVrfvlNrGAILt14N5AaN82gXq9rK/NCEL9h6tuxSM+k0Zf32/LzN5nDVzCVZXN93+30Cta1LXnTk0uN9zkQgx0v89xVEXEy56wdUw+T59Dn0MfQr80ew943O/btfd8YQW6o5n9Vgr9A4eTM2ZXH8zyfiFDBMNFhGGoqm+kwXYVWerMzmn9L+5nT8Tzj42v+/fH8+9fXv35+/tffn//6+fX3x9evz+Pja34d81mogjPT0LRClykLpOWWdLT2pjsaUHcvKd8YLXhS/WVoRTMcUsmPaIRCFo/I/tmL+rshpAOslx3Ma91v6q+9sRfUXKstTZhccGhUZeUb0LxiExXfQMWbUKqLWsBaBsTtQsqquKR+4apFnqwPwsicyfyFk4ycDElzHCqHYjN5muxDHsMew459ZKgEKIGLvJCMUrA7AEbUQKHncZ5PhJuKbEaFwHJ26DBNbsE6rn7dQQiAgHjgdD4P//g6//54/tfPz//6+/N/FLCeH5/n1/N8HnHOmJmtH8JKWGirWrD0lVx66jeb9SVCfwtg9BmtgC5xaZjlay2euN9/aYre4cILMMAVDyhqSlrNXYC7ry3KlmOjp69Hlv5uSFVv4qRs2oJOiuqSh+zbsZR1r8ClEnn/PcqnDrnEaN3MEo1SeREQAQZM759CAgwhTwkTnMKhcih2wzHsGDbnSOqssjM7PU0zUVE1QIkaWjrnPM/jPA6Gb0OHkjQBTHWYjpzsW6mev1+VRGAGjjM+n/Pj8/j569ni6vPvX1+/Po7Pr/N5+HH6OTmT/i4LVVPwXRfagrqfLsvozjfeZAqa0Wxzt26lKPufa+0vuFwwuGHrBtXbwW9P72rqJrF+P5rbb0Cxr6i09PLE68/LtpCXz75uAlqF3qiv61x47bO+vPVB6/syop+ZAyICDlW7LiFA+JpF5AjLtq0KN7p7uIFhIqYy0ujW8m0LGTUVrrr5zH4gXIWkISvgszb11nxGVeW2UUA445xxnv4859fz/PX1/Lts9kTV1+fX8XWcx+lnt/thmSDycrvWCrz8UO437/tK3xbxH5/8f8NxA1QF1K4j11oyj0KA5lWBP10qL2DJ60Xma7tQNqU4OxN5oSol5OowDwy10TYAQnJuWhkEGUStOkRWEyrN92TLWl1DpCraRagpFKt5ZpZ/rWZvlegwqoRhy79yILncimsjeIYf53we59fX8evz+fPX189fn3///Pj758fPX1+/Pp+fz+M45lnTePIcX7iPVzRc/0i7475zv99lrnd9/9lNO/xxef4ssb6h8R9Q+vuivr6uGYRWPcVMpw66A0uu5nbSLhUlZzXmJ2V32tvNyq8u+/OlPHShqSyIDirlGVTdpjSW8zwFGGMMNL8jkR/tATKq5YgSgZhBAWS6CcY5h6rZMZLHjEj2GiRgw2QBy3vAScnNe01yompstgx4qRaPOQTlmPN5nJ/P4+Pz+evj8+9fH//6+etfP3/96+fH3x/Pz6/z65jH9B6qtkyfXgOsJV1KtkXVi8TqaOxL78P+xYsMvb389S+udy5V+BIcwVqSPje5i4bLwlzWnrzgq8wjaTsKbdo2nhaSGldaNeBSpvTCY7V+XT7wUmpN1ZYpucJbnaLfJ9rQbnWrVQ9V2FqvuQErMscZFGCmDBPJ4ZWQQHbxSqJyPnP0NASdcd+NQ8c21CRi+uyZcYSIaLdjtGoeO7YxNsvQoHXYGSAZngHB+fk8Pj+fvz6/fn5UNPBff3/8/fPj5+fxPP2ZNcYsszp7YvXmW/H+a5/1fVyG7LVV2QbWb0Ko4fFqf7XlcT37Zqfx5fMzxNb4voAtd0P8Zjwte7Ddj4yVXc6XLCW0wPT6fNkmor3jsuCiArxsacW+KZ09gaUWwd6x9SpB9eLSSzSuus2RIJPWzg0skpqFy4CLZ+wxym0gwS5YmcFzhunMtkqZtZvMJ0AwGGaKBNZqyigtrbLPpyWkxmZWerV6CVOCdPfjnM/nUTMjPz5//fr8mZHmXx8/Pz4+vuYxYwacGrk2VeXLJUt6CW54WnfnO+HwEuTqfy+8fLek71Y3v727rYbL/WqruCEk678+sRZf9z/X6d6E7JJyt+NW690mVblT6IqBNt4vEKV44uud6fQs9k+r6jp/kreqKxpXJ2zp/t852FHL4n4FVkQO482bFcg5ArDqFZ/tU0APnnA9IahZuWR037/8pDEUiJklU0HJ4P1qupr5yYmq7POpal1sXe3zj3N+PTMm+PXx+fXr8/Pnx+evj89fH18fn1+fT5+BgIYgOxalTLwK0ha07pu/n12K8tUS+oN0umPm+5NG1Dcp9/rPBafK5r508x8e189lIY7r5JfEuuGqu41dkkqlX71O4HYu3+w/WX/im8S6zIDrBmZfT2utUyqwwiZdViQNLFXtnZZfqUpSVZh5s5Gx0nQGqgs5cHoUsLJpNrJGLiVcDBMJj1kDvltMZFnctoaHq21apXOrLQ4j2CkMx+fX8/Pr6+Pz6+Pz6/Pr6/Pr+fV8fj2P5+EOhVg2ovxG0H1D1vcn/2cfrdou+6RuyHcp9fpnQ+mC1B+AVQGL9ZC2cK7jT87JH7fThbbXO5kMAmW1xbhNzV0m87KxLlX4O7Ak2CdaI0FaSEqQ2cRMEWcl75rIqkqrAcbbECURnuVCWhWYQy01YD10DM0JkVX5Xb1ozzPN9mdC6uMzIXVkjtXpPrNuUEVypNSKq9xu//d/lZS6eW2LRu4civ+Ej//usZRun8G629q/+TeQUqCrGuSW4yavwCoJcnP1r5W6nI1lSrVrhbacQH4HFmRJrz5LkWVwSWvA0jhDV99+M7s7ofkBQ6QMgcvfeDkU2dgMLbfIAGYQgDEu/QyAjPDwsQ0dgCBUcqbZyNFqNjYdu45dR4qr0RXuRTRkIOg4z6/n8fn59fH5+evz8+Pz6/P59TyPs2cgByOoIIWZQMyVvyvrvtzhdBlT7btx2UOdTLScuj+Did+QRUBegrRXtR6xoPMNWG3tvNBFjacLUgqRbnjYSHoFVn6udr+mVGRSCZ1S4CkDcJlWC24ZK7s8PiKN96xc1jbn8hQg0GwlalcUrloQS3cga6u1rQPhyM9cMfPfoQURSE4fLZ88nUAPngTgxTXENdhtH5bz74ZlewET22zsOnYbu9lmN1SJWNWAZ1+yGc9zfj2faVr9+vj4+Pr8yhIrzw5Ld73WN2dJgqVzbnjCLWLS0jlnd12IupmpjSp5ocVW4Gv99Ro17qdlECwf8BuwgPWrb1Iq7/Oyk6Sy2C5YLXFw+096mDKW55IR34sI+WYcFuiip1Cy/ItCcnaGT+4nG9MuH9AWqlY7n+t6y1Bft31c8bSbSH6RWJ2yByp6U/R0vDz7qnTxnOB42tx0H7YP46a2KSUbEGw6drWtxdWWg667tSGCcK/u2Z/P4+PrK9OMP7++nsfznLNGLomIcOkatvtWPn1zOxcEbjKmNlVef1z9WK8X3ESQJHj+YAVfqL1LOEHng7cqaVV8yR0QbJh1QzFp8VbVXdJyIOda6GU7yQ26WKrmDptrtzBuW6ZPucGW0FttiepqVZQU5Mx1YE2n04RR4WnoahIFuUGZ1Re3buO4bvl1N2++cUnpzpekQurkA/CbDGCEu8zpburTfLfgJjI2G4RBBhJeOkQHbECt2rykdUXJ4Pe5VOHX8+OrDKzneU53Z0e+VSWuLJeVwXGTWBcMVnxLpGMIr9bVunTpey8vd4PX0xtASyx9v3uNk0sa1Se/WuVYllPf4bKauoa0/tTWNZDrsq6rqyqgFJ0LTukCBe4S+TIGuGIb3jcuz0tBKKtcMM9hWerDMrxr1i25sgFChpazma+/tIsc+O34JrZwPRQ95SkgQjq7sCVIydF7Qlu91HSYdrNyicz1zlL9bEp+K09AthP2mNOPmf02jq/n8XVk/vpZ0/xSTDfn9/vJ/+FyeiXvBhRvxw0Uf/6AP/77N398fdmlBP8ArF7Ivs1YN/vfP25C68U/KTuqJHE3xY4G2A1YeHllDWW9oaj1d0nNblv+4gEu9jXvJ1EjYT3C6RHxb4H1eg+/P26ZQzUYToBJhDCI0Gx7KCqhGsNis9g8TmcirBvYdVspSJTVWV2pT49j+pF1xud5lCfYZVzSW70F6i3l/Iabf0LEv0UjGzD/FrDy7579Dqzr163I/gFYfD25iwJ4vZjfz+2FLFhp1Tf5hf6Q5Q+ibKzrnAUXnqTGN9UQp3Y8yx0hGVXkGr8By2/AIm+wv7meLwpBILImgqHdMAKEVql/VPccIVVDZ4i6mZr5OHwf8zn9mHF6Si+p+RyihGQz6klW9brH4X7WuKLI6eFrSI4aAtQqomrx2ueD6gPCvmU367kT1EWu1KhemyLLl8V7IeU3udQ/+PaTG3rqg4orWEb9eo0AbbDX7WW59peDkb1jQwANgUhIm4+Q23fzymhpHqF/FhfCEFgRlCuyGVx3R1EMVcZFhpnpGGqqNlYYFzX1K8vlAtk5q4FVtQkLWGV1dE1Zu6nfbmPeFF1nJYL73ohMtiQEcOJ0qDKLyVSn2TlsPJ7zefrZPU4DQpHIeeFNuJ/uM7wyIyKmc/Yw9FSCapq1ngWmKgBv0bU86V7OWi5ZhkTFfjLFGDfblk1EFEBbg/5J+C2sLdlz4RBNZPfqLxC0xLp5ef36unlrASRvqERxiXWw4zYX90GspSxqgfdO8d3v5JrY2EKh0VydKVPrVSM8y//u2b2C8gwSTN6P+mdk15SIPB0Bx/28bo/7/ayLL48MCgSxKpxYfXwRQQrgpFJOh0h2VZ2qOswez/15zOP0mj2E6m0vQQg84sxHdjaLzF6vlJgoVGjOhK4GRzmMJdukLWmDkppIqaBri2dWsqSLLiuRdLE/ZXgBHZ2VMqTuSkjuz17lEF6V4PXiV0UtDfhLuVyv4fov2Qvybl5loqlesq7elP5gv7VF2EXURXT/uFx0EKJgMkHdKLAG/lZmQKLK2qJqZyen5s3wGe6MWSM66Y3lWPt0LBX83dQrtbhua0r4JNOqSCEHYcjaNlXlSS9ZVDP2RGWoPd7Oz+P8qplpkU3P1ZWg4FKCZydynREzR4wWiro8gNQUQpHDg3Tth+I9W8xki/t27+s/LWmVY9nSvrsnzBBVPvqb5cZXdC2D6Vrl78D6/o42vJbIyoLfvJpCRBKGeVeLUcByEwkqa4pKLcpNYpV7fhcRK4Fg+YttQ7b0XsAyXaER61FCkhKfjarik3wePmf4ZOT0hJW524YUS2LdkLTO67dNBqDS2sGO9+r1BgHSrMs5RMzBlQG4qGx2fj3Pr+f8OubXWQ8ZBpERFOGMNqqm3+G1yti5uKru/SMQ5OiFXPcWPZd2q1TyXso6X1EoCSE0M7hvXWX+3zjupvpdCcq311yKsCWWtEGNu0bDZew135A1BcRiwPK0m1nAJR14M7nuFn1r9rKW9QapoR31ywBunT4vRsHn9Dnnec7zmOcZ82RU/gEyNeV2nf/eK/zj7auLzYu6gbFuS+QXREENEnr6c/jXUeWmn1/Hx+exb0+KRMQ2TATBmJ6TRb8/MpnPb6Lof/qQy2bCUi5aBRJt3fyvffT/GUelXMqVvHHnHRakcAfWnz9peS89umiRCTlzryP6C+g57vgKqmT31fM4zzPmiQhJzSA9ubS+BqOR3cQZb/L0fkJtqt5/3Msht7qDtTfgqS2dqvE8/fn/6u5ql+TGbSAAaWzf+z9qYu+ORKLzowEQ0sztxZdKVSo6eW52vkSRTaABgsBx/vo8fn48//Hz49v3b2Y63MePx7fHY98Nwp2MeWa+q3NEIaQJRMnqMO+S3+TdlMKL9orkqn+u0SZnUjPuOXTArjeOpdK10nGg/es3v5jC0ksS7GjJqa44NSlFStkwhb5CNYDmigs3Qv75AqyyDzu1YevisgwJiOCXCAgwFrbYlCu2DuasogZkPlX4GOcxjud5PsfxHOeJcQLYJBJgX1YNVfbssq4iFw/ORl06KL4Kkdgfh5o8IsKa5Q4YfApY8e4Y8/MYvz6Pf/z6/P7PX9u+OXCMcZzf//jx7du3h23K4rxj4hx+jnme8xjjOMcxBp3udJA5vcytPWnlJLlB/ZXBJFY3rAJRh5m4iiETgqyVQ672ZNKjhqrlD0rDJqd2oJxJPmoPQEGtk6x6giKFrcfXzzYk6wJptMPp+suf68BKPEmuui1Q8d4jMjBTKzLikn9z85azPAtzqbg7JnzOOTEDWON4juNznCfmqRCY7RtL+YnolhNN90TPhQBLF6YpprolUu9FvypkbTtWlk30qCKNMf3kVubP5/efH4/dRGXMmS71P374fOy7qhysNRo5zcYxojryZDoduv4lDNFrprkUqSaxrbsCwXN1JI09Vo3lHlvPpfWskMYniqg/FFWIglCvvqiRLChXj2ZuzvR0YGniElTBq6rr1wZ8Lb+XrOt0jy0SkpLENl4qMpKG1LI2REwzUx7X/2K3AW3ATTWKFIvInB7wBfOKs37exDg7sOY4ZQ4VxRY7kREXCK6RHKvQteZRQC0nkK71+was7Gddca01wTW06nDY9OMcvz6Pff8wUxeMMY7znGNM+AR+fHczizrb5zziZEmn6Q6oRjH26En13r/RyhJMjSE3wz5G38TEAkbquGhDBcQjC1vEzq7+KYXT7rMzNxGTzEtcn7tqxXyrDf6aHkvM3b6Zv1f/aaKoWpFaJhJZSYrScGqHEcrc8bGT5cEKxRm+S4mdafJ9pqxy0pFznMc8jnE+53HM8xCfpqrYN1OYM7l1mie6X9q+2iHZtJfeuZk5FymWZoqIqGvE2ITQOsbcngfTIbv4nPOcE1RGqtN937fjPJlBlBqQRuJg6VTagAzNDvOgD3k2BnkjWgttnQnl2KqrUh6x+HyREyR2XF25sP23jUattYpSRu2XmsSqT9+ElVz+QFm+5XiTAtYCu/YeKYagYsZaBBRYkeRu322zDDJ3oHzphNQMj3UA65znMY5jHoePU3zSJ+HTsGf+27zH3cyamU6z7je67s9fD58Af3xCxvTjnB/PQyNHxJxMrripGIG1j3H++nx+Ps8nK7mzNi6rzjfmG4lZE203Cv1nbbo28EobwzZcZjqzAGZh9/+RI/105U8J5R5TuX9UhTETES7B/J6sSxmV0JY9aCKaMS+yWD+ibluWKL4cPlngBZuZ+7YqsObRgCWhZEwczqnKu5GaY9f7VF0DtEhoanaVcEUyplmGi81pB8cKrHdLM8Uh5zkfj23M8c9fHz8/PjNgtPxYwVM1VgIJLIiEDBOR2JaifMaFNcuVpwBgI9H12YSVpJXnjExSMSuKjfTm997LaCgVySWaEAwrsFNkSay/lHwXKpX92Z563o33D6Wdgab1JG4/wm4sSh/avm2bbrlks0UUKKWcqfrSQNVvlwOJOxo7NRURaz0V0yv7vm8kfAz7govBYMG8Yz4UCwDKDVYjclkTlfySJOcgG1C4YLjoGCLumHOSOvH1+fk8Ho9t+vz18fnz58fn53GcY87YjhHlhsH4GgpVRWQ31hRTK+waLDK+SmKRu/dlO5qT7RWNmcXtic68DwZ1jRwQ6Xqor2DhswNLadJHD6jI6smOqwu+9AVvitJ0zaISJkVfwFIty0ojpUzEwUfgp0aEAkuI0V/FxeattuFTfxYorZa8Eel1YJorlpzLmi3LRPAovKkDKtj3bSeuFNDJlWtjuu0kH8UMY3iLtiSDSEOs5j1i2DiDC5LTiew5XecYrAw93Y8x//jxfOy7w5lf9OPzeZ5zzojuiJVU1k1OAHBjh4Rtlk4FOv8UMFMSqATBWiFccqv9q+nirmYWjIa5c8oBnBAMolZ9IOVUq0WbtjObn00XSS5sXgLmqw2AtFDxsiqy+0M6LGDW8o5k8KmKRZHZCPy0zSyAtdOrHu710JIpCVjJyRQeoFIz7sCCmWzms4fQmGgkY+KIMNZZ4VzjD4kFmMMnJaC5m6lP01o1S6549Y2o5nb/0Jpt4S3erzoDqHqrzgVm0zG5pOnHGB8fj8e+QXCc5+fz+fE8jnPMDB4GiwbG83IF5B7VMnlU1czoPQAMxgUCZBLesFiQtLaYfoxt+rNNhLvfTGMbXN63poDOjzZZFVNMMsFngPZG0jQD5V9EvywwyX05pkwLOi0Ti8FYohWJjC3KNNryqm+PWLqxLCSmGhmsINk3QnEF0w0mkbZjEzDEaVoF+9FHjwh8ZXNZhEEV6q6iO1Nmg3X7AEA9EnRUBgH6dvJeYyAh63ZSRJXEkprVnBLcS6ruIo6JqeJTZSQ1P8f49tj3fYdgznmO44gtOatAHp97Pi5J2oFlZomoehMcSwCX6PFkR2mStZEP4UK4RAB4fiF1bT2tPkhamUqvZFxd5GIV3ZVjtAct0i2tqbzVpW6wfjrBzvonZrF7c6sFG1YvMm6228x2bmhusTrMV04ZQO0XJ3NAA2qmqHQjZrptOmcDVmDH4eLRH3sKUr0ey07PfkGTWGmkXQbk5VBp7KvqJjJEyKeAVaydzojHtm+bqDBj2+ipH/KM4J+sIHED1hfW4FIWb46XT7+YgQWcBazlJHuRWA1Ygarss+IEegXc/fr10GcHrufq4zQQtLIqtF3wm61cUY+QWLHZLku3IeOAvfwzdeI+xKvbzIJokG8hI9+TXN8XofX9GZCoTipj7DYud0bagRV1JqJnIsBgipzDRabPzcJNx+LpBJZ3YOEGLPwlsDjHVdUBc3+Dq0j5tpAnS+OUzSJ6k1iti8NmeA+sJE5sCl/PaVreVi/xVKTjFVhCdovex6pZnZxyhHiySJW45WJg1b1ewFL6F2RGnLFzVBHpjnLQU/P2EHl2mplBNkYhSlaQnCJM1KCxCN10eXGDBdvYC7LuiiE6Gs1IGZ5Yepnvq5/YKJipcy2FuZkhYwLOLU+LR6QeLLIhJfMK5FgGQ2O3/HrMHgJL/Q4rSbYv3JEZsGokuonnBa+0gS/P1wxqyimJdbPZ78DyQF+NHskoLm24Dk3+fLS3IBXb33Pr3xbYIq62vXafV7lxrjnCXcBwARIhIJNgrGHwyHKWzipTxbaJigJ08sAxZQKwvPfdnUsjHZWBLV7AMrg3eQ37Ebn/vknu0pE1Dos/cAgNBpYfkOXM4HI61MMSDUshOjMSjqC8HqkZOoTD8I45EmZUYUtKpmnabHzRQl5FhpZ6N+ZvOmHJtLOa6UV2aWqjGvJklxI8VLXKA7bWIjpdACjcHeKhl9pMpJRiZ9UrYXgIZRUV33bfUJob4ZmILFL7GIElKiIT4g5znerqwo1WGytkh6BwIabCxJoMaafEiuWbDMYC4DNns4iI7O4zpw+tthxPWcouY8uRJjMqI0Bb78htdomly1yVENwslasqrOvHiUF3VoZHrYCxamVKJcJuYbngRVSFImsaUC7XvzCtBY5K/VMei8oJu2I1KX86ay4ZXb+PBTqhC6/Sn9UPl+ilOBDAJ1RJfz2me+7JDj9Hu0b2rYokqsJUo6CiHoycPlaPj4iO2TZW04QYMB0sHs9hgym0ygzRFA9ghbe9JBbDthijDhcPXElbqw+JJdzKGiWNkPUSl7jSlj9QU4ysUe43fhH8154X1c0yn6XmbMw0AikekJYWMZMMMl2GhbW3EgvQ9AP1x9sRQ9/txEpeFq5Bymwl6ARZ/h0SNv71Z3X1jmZJofarmWOoWsummsFdKatol9fUyC5MwlaeLZX14yyQpxq17SPH0OVc2amr8Adj57HCwOgViCkQLA8UVwhXI833lFgMkqRvyYXmoLi7V72rBqylCkvfUSEmt+ocq59tqBebenMk6CKCJWaFp8oL90xpI82YowvHwB1Sr0cf8lKLLzhQKab5DlgkxWSSKE9iJNaLrn1j5FQCxmVbRaBhbKK6AsudPFMB9aslfr/Pmp/oPqemDZO5/8nJDyjri2L1P6cMJXQKi761yxeq4J4rLWqqEV0Ez9GDOwtxQ0T2YMi56nPh7xcK3yVRQSqFyFIN/fGvjyLmhQBexfovvgLr3/nlxNMXcouvF1kSESQlYswFxRNi64Uhd/qYaS6EWkmmRU5q9z+7q4Gs3ff1rReQ5pdf+usVzt3XcD+ZYapfYsnCi3QoPCWkLmdJnMUv2w3UUC5rmhIrRs/T0k66oy2yfanDLO6AKgrSB7sLsALGVwfK2dk+561LSzMsXNWEq77WrxRfwev10IxD4uV5Z+QZlvmELGMG1xJcPmg4+w1QZskwNXGBmaBskfKxd+Xd7v7l1OVnDXYnDBPSy5dVIk1gLXnfz0WRXSW204jo8vrAxR0+xSOw3ed0H8nWp8fmwWDCZdxwmni3dqKx0b4dQeSx4Jbmbk7C3AOtwqSkEiYhB9albv9C2PtA4oqKVxheJypqBChL30ss9B9od3U7XiHVJNR6NwxJOr267ZJqUWMBLnN+aj2Yw0wNtNQ1kj4JI1Qz9nlJ95pLKQbQ/CohKGu2BIEAKkIXSCKanaVShDiVWjiD6rohhzTKVod3cK7dp9zbFeeYsdg2Z5h0MTNRnRySS2SRg2qHiIjs7qW87q6sGoIS8ynp2+eXUOMFEzYrmOMWLXIFCLAqk1yNuDbicVNApv4pDfpvHMXlO6raJBPUFXJqUTUEtigSTM1sZhrZzPppZoZtUxjMIJtJ+SXUGEDLlVleYUks5MVKy3j6FHKJOsUVsaPhjrjMTNKchFHeYLZZQseVgpuMLiVO3SUqpLtjTsyB8iysLakT7rVXX2OWS9Y7lXB7JGfVcKyIiOwI8RjyBmGGIc2iGPJcVGZUEzuBaxMuDYkN0+uPPh2vsj8HPKGfgCqP7oL6G2X7+8cNUqkHBRk/GfIbHmqC0fEpscqwRwFs2zaBIUsUq1r44zz9Mxo270ViJapiWWWtfaoIJCuFLfGAglrEyV26A9LoWrLT2MEjAMRjB4JHEYHct7xYVOX2iEefFaLcVifD+3JlgVqo0nRsapD3NVxLltQ9lQGyuF9K5DdjfFdH9z64XeWrb+a9/A3m/vVxg5ek0IqcFpQfWZZeBU6JBQNjSGQriiq5VmeursrcORZrt+sILLWd9Lej3+E75s6RI/3tsyxG6u25uixUoda44gVYC14Z9e6LudcYXLuxP14tFPz+htX/54PgegVWU0pN7mdvalllSBH/v3vgGmPh64STyPOM28ffn8p7qqNQhV1wFCSv86Da+MUl3/Po3zooURvr+y8e3SvRjRgwP4RIcs7Y4P4qkEqMv7z4RdNxPS+HXv53e3o//kRiXS/UzNP7ldEpdpCVMtWbQP2NYX2RWFhW7r3hbw+0z1xe/Y+wdeGo/+WjZHzj+KWepN1hoUbe4amo5P1n32HrLeDWi6+oqj/1LznE/fX+cVxfegOu64nLZ69X+nqA/wWVYh2efIE+UQAAAABJRU5ErkJggg==",
      "text/plain": [
       "<PIL.Image.Image image mode=RGB size=200x200 at 0x7FA9D072E0A0>"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# show the first image of the testing dataset\n",
    "image = dataset_test[\"img\"][0].resize((200,200))\n",
    "image"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The image is not very clear, even when resized. Let's extract the actual label."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 'cat')"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# extract the actual label of the first image of the testing dataset\n",
    "actual_label = dataset_test[\"label\"][0]\n",
    "\n",
    "labels = dataset_test.features['label']\n",
    "actual_label, labels.names[actual_label]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It looks like the image represents a cat. Let's now see what our model has predicted. Given we saved it on the HuggingFace Hub, we first need to import it. We can use ViTForImageClassification and ViTFeatureExtractor to import the model and extract its features. We would need the predicted pixel values \"pt\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import ViTForImageClassification, ViTFeatureExtractor\n",
    "\n",
    "# import our fine-tuned model\n",
    "model_name_or_path = 'LaCarnevali/vit-cifar10'\n",
    "model_finetuned = ViTForImageClassification.from_pretrained(model_name_or_path)\n",
    "# import features\n",
    "feature_extractor_finetuned = ViTFeatureExtractor.from_pretrained(model_name_or_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "inputs = feature_extractor_finetuned(image, return_tensors=\"pt\")\n",
    "\n",
    "with torch.no_grad():\n",
    "    logits = model_finetuned(**inputs).logits"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now see what is our predicted label. Do extract it, we can use the argmax function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'cat'"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "predicted_label = logits.argmax(-1).item()\n",
    "labels = dataset_test.features['label']\n",
    "labels.names[predicted_label]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And the answer is cat. Which is what we would expect."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## References\n",
    "\n",
    "[Article](https://pinecone.io/learn/vision-transformers/)\n",
    "\n",
    "[1] Dosovitskiy et al., [An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale](https://arxiv.org/abs/2010.11929), 2021, CV.\n",
    "\n",
    "[2] Vaswani et al., [Attention Is All You Need](https://arxiv.org/abs/1706.03762), 2017.\n",
    "\n",
    "[3] Saeed M., [A Gentle Introduction to Positional Encoding in Transformer Models, Part 1](https://machinelearningmastery.com/a-gentle-introduction-to-positional-encoding-in-transformer-models-part-1/), 2022, Attention, Machine Learning Mastery."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.13 (default, Mar 28 2022, 06:59:08) [MSC v.1916 64 bit (AMD64)]"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "5fe10bf018ef3e697f9035d60bf60847932a12bface18908407fd371fe880db9"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
